Primeiro acesso

Olá! Nesse tutorial você irá aprender a replicar tudo que será exibido nessa página!

Para isso, você precisa ter instalado em seu computador 2 programas: o R e o RStudio.
O R é a linguagem de programação e o RStudio a interface gráfica,

Você pode baixar o R e o RStudio através do link https://posit.co/download/rstudio-desktop/

  1. Se é o seu primeiro acesso, clique na caixinha Code no canto superior direito para baixar o código no formato .Rmd, ou seja, RMarkdown.
  2. Abra o RStudio
  3. Clique em File -> Open file -> e selecione esse arquivo .Rmd que você baixou.
  4. Você deve chegar a uma tela semelhante a da figura abaixo

Na primeira vez em que for rodar os códigos aqui no R, será solicitado que instale pacotes. Quando aparecerem caixas de diálogo, clique em Yes.

Pode demorar um pouco esse processo. Para ter uma melhor visualização desse tutorial pressione as teclas Ctrl+Shift+K ou clique no botão Knit acima. Recomendo manter uma aba do navegador com o arquivo tutorial_R.html aberto.

Já podemos rodar o código pela primeira vez!
Para isso, aperte Ctrl+Alt+R ou clique em Run no menu superior e depois em Run All:

Enquanto os pacotes estão sendo instalados, prossiga com a leitura. Deixei alguns conteúdos nas Referências que irão complementar esse documento.

Quando quiser renderizar o código para ter a mesma visualização como a do formato .html use o comando de Knit, o Ctrl+Shift+K, ou caso esteja com um gráfico aberto, clique em Viewer na janela inferior direita.

1 Comandos mais utilizados

Ctrl+Alt+R -> executa TODOS os códigos de uma vez só.

Knit ou Ctrl+Shift+K -> roda TODOS os códigos de uma vez só e renderiza a visualização em formatos .html ou .pdf.

Ctrl+Enter -> executa um “parágrafo” de códigos.

Alt+Enter -> executa o “parágrafo” de códigos mas sem mover o cursor.

Ctrl+Shift+C -> para comentar ou descomentar um intervalo de linhas.

As linhas de código que começam com # são comentários. Elas não impactam o resultado final do código.

Ctrl+Alt+I -> cria um novo code chunk.

Ctrl+I -> Indenta o código (ajusta a tabulação entre as linhas, facilita a leitura do código).

A lista completa de atalhos pode ser conferida no menu superior Tools -> Keyboard Shortcuts Help, ou através do atalho Alt+Shift+K.

2 Passo-a-passo

Importante: Com esse arquivo .Rmd você deve chegar aos mesmos resultados que presentes no arquivo tutorial_R.html.

Vou deixar comentado os pedaços de código que necessitam de alteração obrigatória com a nomenclatura alteracao_ seguido de um número.

Para encontrar facilmente os locais que precisam ser ajustados, basta utilizar o comando Ctrl+F e procurar por alteracao_ e o respectivo número listado abaixo.

  1. Renomear a planilha a ser importada pra facilitar a leitura.
    • nesse caso renomeei a plan gerada pelo RSÁgua de Dados_20221222143305.xls para plan_litoral_medio.xls.
    • você pode usar Ctrl+F e substituir todas as ocorrências de plan_litoral_medio para o nome que você deu à planilha.
  2. Ajustar o caminho do arquivo. (alteracao_1)
    • nesse exemplo estou importando diretamente da pasta de downloads do meu computador: "C:/Users/Léo/Downloads/plan_litoral_medio.xls"
    • Futuramente quero implementar a integração com o Google Sheets.
  3. Verificar o intervalo de dados da planilha. As últimas 10 linhas costumam ser dos sumários, mas o R não entende isso.
    • verificar até qual linha a coluna Índice tem valores registrados, neste caso o Índice vai até 98 (+1 linha de cabeçalho) = linha 99
    • Alterar na parte de importação o intervalo para compreender somente os dados (alteracao_2)
    • Estou tentando descobrir como economizar essa etapa.

3 Pacotes necessários

No code chunk abaixo serão instalados todos os pacotes necessários. Cada pacote contém funções específicas que auxiliam no desenvolvimento da atividade, seja a importação do dado (readr, readxl), na manipulação dos dados (limpeza/tratamento com janitor e lubridate), na visualização (ggplot2, rmarkdown, kableExtra) ou pra praticamente tudo (tidyverse).

pacman::p_load(
  # ETL (extract, transform, load)
  janitor, readr, readxl, lubridate,
  dplyr, 
  tidyverse, 
  glue,
  # Visualização
  ggplot2,
  GGally, 
  rmarkdown, 
  knitr,
  kableExtra,
  ggbeeswarm, 
  ggtext
  # bookdown
)
#googlesheets4

Para acessar a página de ajuda dos pacotes ou das funções, basta usar um ? antes do que se está buscando.

No exemplo abaixo estou verificando os argumentos da função p_load, do pacote pacman. Na sequência abro o menu de ajuda do pacote tidyverse, um dos mais importantes da comunidade R. Outra maneira possível seria utilizando help(package = 'pacman').

?help

4 Importação dos dados

plan_litoral_medio <- read_delim(
  "https://raw.githubusercontent.com/leonardofwink/tutorial_R_fepam/main/planilha_rsagua/plan_litoral_medio%20-%20Dados_Ajustados.tsv", 
  delim = "\t", 
  escape_double = FALSE,
  col_types = cols(
    ÍNDICE = col_number(),
    `CÓD. ESTAÇÃO` = col_character(),
    LATITUDE = col_number(),
    LONGITUDE = col_number(),
    `BACIA HIDROGRÁFICA` = col_character(),
    `RECURSO HÍDRICO` = col_character(),
    REGIÃO = col_character(),
    MUNICÍPIO = col_character(),
    AMBIENTE = col_character(),
    `DATA COLETA` = col_date(format = "%m/%d/%Y"),
    `HORA COLETA` = col_time(format = "%H:%M:%S"),
    `CHUVA 24H` = col_character(),
    ALCALINIDADE = col_number(),
    ALUMÍNIO = col_number(),
    CÁDMIO = col_number(),
    CHUMBO = col_number(),
    CLORETO = col_number(),
    `CLOROFILA A` = col_number(),
    COBRE = col_number(),
    `COLIFORMES TERMOTOLERANTES` = col_number(),
    `COLIFORMES TOTAIS` = col_number(),
    CONDUTIVIDADE = col_number(),
    `CROMO TOTAL` = col_number(),
    `DEMANDA BIOQUÍMICA DE OXIGÊNIO` = col_number(),
    `DEMANDA QUÍMICA DE OXIGÊNIO` = col_number(),
    `ESCHERICHIA COLI` = col_number(),
    FERRO = col_number(),
    `FITOPLANCTON  - CIANOBACTÉRIAS` = col_number(),
    `FOSFATO ORTO` = col_number(),
    `FÓSFORO TOTAL` = col_number(),
    MANGANÊS = col_number(),
    `MERCÚRIO EM MICROGRAMA POR LITRO (UG/L)` = col_number(),
    NÍQUEL = col_number(),
    NITRATO = col_number(),
    `NITROGÊNIO AMONIACAL` = col_number(),
    `NITROGÊNIO ORGÂNICO` = col_number(),
    `NITROGÊNIO TOTAL KJELDAHL` = col_number(),
    `OXIGÊNIO DISSOLVIDO` = col_number(),
    PH = col_number(),
    `PROFUNDIDADE COLETA` = col_number(),
    `PROFUNDIDADE TOTAL` = col_number(),
    SALINIDADE = col_number(),
    `SÓLIDOS DISSOLVIDOS TOTAIS` = col_number(),
    `SÓLIDOS SUSPENSOS TOTAIS` = col_number(),
    `SÓLIDOS TOTAIS` = col_number(),
    `TEMPERATURA DA ÁGUA` = col_number(),
    `TEMPERATURA DO AR` = col_number(),
    `TRANSPARÊNCIA DA ÁGUA` = col_number(),
    TURBIDEZ = col_number(),
    `VAZÃO RECURSO HÍDRICO` = col_number(),
    ZINCO = col_number()
  ),
  locale = locale(
    date_names = "pt", 
    decimal_mark = ",",
    grouping_mark = ""
  ),
  trim_ws = TRUE
) %>%
  janitor::clean_names() %>%
  slice(
    1:(n() - 8) #retirando as ultimas 8 linhas
  ) %>% 
  rename(
    e_coli = escherichia_coli,
    dbo = demanda_bioquimica_de_oxigenio,
    mercurio = mercurio_em_micrograma_por_litro_ug_l
  ) %>%
  mutate(
    municipio = str_to_title(municipio),
    data_coleta = ymd(data_coleta),
    ano_coleta = year(data_coleta),
  ) %>%
  dplyr::select( #reordenando as colunas
    c(1:10),
    ano_coleta,
    everything()
  )
plan_litoral_medio_alterar <- read_excel(
  "C:/Users/Léo/Downloads/plan_litoral_medio.xls", #alteracao_1
  sheet = "Dados_Ajustados", 
  col_types = c(
    "numeric", "text", "numeric", "numeric", "text", 
    "text", "text", "text", "text", "date", 
    "date", "text", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric"),
  range = "A1:AY99", #alteracao_2
  trim_ws = TRUE
) %>% 
  janitor::clean_names() %>% 
  rename(
    e_coli = escherichia_coli,
    dbo = demanda_bioquimica_de_oxigenio,
    mercurio = mercurio_em_micrograma_por_litro_ug_l
  ) %>% 
  mutate(
    municipio = str_to_title(municipio),
    data_coleta = ymd(data_coleta),
    ano_coleta = year(data_coleta),
    # hora_coleta = parse_datetime(hora_coleta),
  ) %>%
  dplyr::select( #reordenando as colunas
    c(1:10),
    ano_coleta,
    everything()
  )

5 Sumários estatísticos

sumario <- plan_litoral_medio %>%
  dplyr::select(cod_estacao, oxigenio_dissolvido, ano_coleta) %>%
  filter(ano_coleta > "2013" &
           ano_coleta <= "2025") %>%
  group_by(cod_estacao) %>%
  summarize(
    min =
      min(oxigenio_dissolvido,
          na.rm = TRUE),
    q1 =
      quantile(oxigenio_dissolvido, 0.20,
               na.rm = TRUE),
    median =
      median(oxigenio_dissolvido,
             na.rm = TRUE),
    mean =
      mean(oxigenio_dissolvido,
           na.rm= TRUE),
    q3 =
      quantile(oxigenio_dissolvido, 0.80,
               na.rm = TRUE),
    max =
      max(oxigenio_dissolvido,
          na.rm = TRUE))

sumario
output
## # A tibble: 6 × 7
##   cod_estacao   min    q1 median  mean    q3   max
##   <chr>       <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl>
## 1 87332500     0     3.3    4.94  4.75  6.73  9.23
## 2 87420130     8.14  8.58   9.06  9.15  9.67 10.6 
## 3 87420150     6.7   8.19   8.41  8.49  8.64  9.83
## 4 87420350     5.93  6.96   8.34  8.07  9.23  9.64
## 5 87420500     4.65  6.43   7.25  7.50  8.73 11.0 
## 6 87510010     2.32  3.72   5.9   5.53  7.30  8.24

5.1 Visualização da estrutura de dados da planilha

Conferir se o tipo dos dados está correto, data em formato de data (date/dttm), código da estação como character (chr), valor medido dos parâmetros como double (dbl).

glimpse(plan_litoral_medio)
output
## Rows: 98
## Columns: 52
## $ indice                      <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,…
## $ cod_estacao                 <chr> "87332500", "87332500", "87332500", "87332…
## $ latitude                    <dbl> -29.91447, -29.91447, -29.91447, -29.91447…
## $ longitude                   <dbl> -50.31819, -50.31819, -50.31819, -50.31819…
## $ bacia_hidrografica          <chr> "Litoral Médio", "Litoral Médio", "Litoral…
## $ recurso_hidrico             <chr> "Lagoa dos Barros", "Lagoa dos Barros", "L…
## $ regiao                      <chr> "Litoral", "Litoral", "Litoral", "Litoral"…
## $ municipio                   <chr> "Osorio", "Osorio", "Osorio", "Osorio", "O…
## $ ambiente                    <chr> "Lêntico", "Lêntico", "Lêntico", "Lêntico"…
## $ data_coleta                 <date> 2016-06-29, 2016-09-26, 2016-12-14, 2017-…
## $ ano_coleta                  <dbl> 2016, 2016, 2016, 2017, 2017, 2017, 2017, …
## $ hora_coleta                 <time> 10:50:00, 11:05:00, 10:21:00, 11:00:00, 1…
## $ chuva_24h                   <chr> "AUSENTE", "AUSENTE", "AUSENTE", "AUSENTE"…
## $ alcalinidade                <dbl> 35.0, 11.0, 7.7, 42.5, 22.1, 14.9, 19.4, 3…
## $ aluminio                    <dbl> NA, NA, NA, NA, NA, NA, NA, 0.0015, 0.0120…
## $ cadmio                      <dbl> NA, NA, NA, NA, 0.003, 0.003, 0.001, 0.001…
## $ chumbo                      <dbl> NA, NA, NA, NA, NA, NA, NA, 0.002, 0.016, …
## $ cloreto                     <dbl> 27.80, 10.10, 9.60, 14.30, 10.10, 8.60, 8.…
## $ clorofila_a                 <dbl> NA, 2.19, 7.64, 40.10, 5.53, 3.56, 2.67, 1…
## $ cobre                       <dbl> NA, NA, NA, NA, 0.0040, 0.0020, 0.0030, 0.…
## $ coliformes_termotolerantes  <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ coliformes_totais           <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ condutividade               <dbl> 123.3, 81.0, 66.6, 139.1, 65.4, 69.0, 75.6…
## $ cromo_total                 <dbl> NA, NA, NA, NA, NA, NA, NA, 0.002, 0.009, …
## $ dbo                         <dbl> 3, 1, 2, 4, 2, 2, 2, 4, 4, 1, 3, 3, 1, 2, …
## $ demanda_quimica_de_oxigenio <dbl> 31, 15, 27, 24, 14, 17, 32, 40, 38, 23, 22…
## $ e_coli                      <dbl> 173.1, 28.8, 122.3, 770.1, 49.6, 34.7, 344…
## $ ferro                       <dbl> NA, NA, NA, NA, 3.120, 3.550, 1.940, 2.960…
## $ fitoplancton_cianobacterias <dbl> 171, 47, 1368, 129, 438, 68, 242, 2901, 18…
## $ fosfato_orto                <dbl> 0.071, 0.101, 0.089, 0.184, 0.109, 0.118, …
## $ fosforo_total               <dbl> 0.105, 0.202, 0.220, 0.233, 0.113, 0.184, …
## $ manganes                    <dbl> NA, NA, NA, NA, 0.051, 0.045, 0.066, 0.112…
## $ mercurio                    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ niquel                      <dbl> NA, NA, NA, NA, 0.0055, 0.0140, 0.0055, 0.…
## $ nitrato                     <dbl> NA, NA, 0.15, NA, NA, NA, NA, NA, NA, NA, …
## $ nitrogenio_amoniacal        <dbl> 0.032, 0.135, 0.530, 0.603, 0.174, 0.163, …
## $ nitrogenio_organico         <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ nitrogenio_total_kjeldahl   <dbl> NA, 0.910, 1.350, 0.684, 1.120, NA, 1.907,…
## $ oxigenio_dissolvido         <dbl> 5.11, 6.39, 6.77, 3.25, 7.63, 7.50, 3.56, …
## $ ph                          <dbl> 6.48, 7.10, 6.21, 6.67, 6.73, 6.71, 6.27, …
## $ profundidade_coleta         <dbl> 0.88, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, …
## $ profundidade_total          <dbl> 2.40, 2.75, 2.75, 1.75, 2.15, 2.75, 3.00, …
## $ salinidade                  <dbl> NA, 0.04, NA, 0.07, 0.03, 0.03, 0.03, 0.07…
## $ solidos_dissolvidos_totais  <dbl> 100, 74, 123, 100, 87, 57, 86, 152, 20, 11…
## $ solidos_suspensos_totais    <dbl> 5.0, 15.0, 5.0, 13.0, 5.0, 21.0, 11.0, 15.…
## $ solidos_totais              <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ temperatura_da_agua         <dbl> 14.40, 17.43, 24.89, 23.30, 16.01, 20.36, …
## $ temperatura_do_ar           <dbl> 13.00, 16.00, 19.50, 23.00, 17.16, 21.30, …
## $ transparencia_da_agua       <dbl> 0.4, 0.2, 0.3, 0.3, 0.3, 0.2, 0.3, 0.3, 0.…
## $ turbidez                    <dbl> 23.00, 12.00, 49.10, 23.50, 15.50, 79.60, …
## $ vazao_recurso_hidrico       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ zinco                       <dbl> NA, NA, NA, NA, 0.0150, 0.0240, 0.0190, 0.…
# str(plan_litoral_medio) #outra maneira de visualizar a eSTRutura 

6 Requisitos pra gerar os gráficos

6.1 Definir o theme

Definindo uma cor de letra e de fundo padrão a ser adotada nos gráficos.

theme_grafs <- function(bg = "white", 
                        coloracao_letra = "black") {
  theme(
    plot.title = 
      element_text(
        hjust = 0.5,
        color = coloracao_letra,
        size = 19),
    
    axis.title.x = 
      # element_text(
      # color = coloracao_letra,
      # size = 15,
      # angle = 0,),
      element_blank(),
    axis.title.y = element_text(
      color = coloracao_letra,
      size = 15,
      angle = 90),
    
    axis.text.x = element_text(
      color = coloracao_letra,
      size = 17),
    axis.text.y = element_text(
      color = coloracao_letra,
      size = 17,
      angle = 0),
    
    strip.background = element_rect(fill = bg,
                                    linetype = 1,
                                    size = 0.5,
                                    color = "black"),
    strip.text = element_text(size = 17),
    panel.background = element_rect(fill = bg),
    plot.background = element_rect(fill = bg),
    plot.margin = margin(l = 5, r = 10,
                         b = 5, t = 5)
  )
}

6.2 Criar função para gerar boxplots com percentis 20 e 80

f <- function(x) {
  r <- quantile(x, probs = c(0.10, 0.20, 0.50, 0.80, 0.90))
  names(r) <- c("ymin", "lower", "middle", "upper", "ymax")
  return(r)
}

7 Gráficos

7.1 Alterar nome e/ou ordem das estações

Atenção: Tomar muito cuidado com a ordem que estão dispostas as estações. Deve-se sempre respeitar o sentido nascente -> foz.

Conferir a ordem das estações através do mapa interativo, QGIS ou Google Earth Pro.

Elas acabam ficando fora de ordem por conta do código de ottobacias Para reordenar as estações, atente-se à função scale_x_discrete.

Neste exemplo iremos aprender a como mudar o nome das estações e reordená-las.

As estações estão na ordem certa, mas quero alterar o nome delas, como faço?


Utilizando o code chunk abaixo nós alteramos os nomes das estações para PM (ou Ponto de Monitoramento) seguido de um número. O PM1 representa o ponto mais próximo das nascentes, enquanto o PM6 o mais próximo da foz.

scale_x_discrete(
  limits = c(
    "87332500",
    "87420130",
    
    "87420150",
    "87420350",
    "87420500",
    "87510010"
  ),
  labels = c(
    "PM1", "PM2", "PM3", "PM4", "PM5", "PM6"
  )
)+


Perceba que iremos trocar a ordem das estações. Antes a estação 87332500 era a primeira a ser listada dentro da função limits = c(), ela era, portanto, o PM1. Agora o PM1 será a 87420130. Compare o código e o gráfico abaixo com o anterior.

scale_x_discrete(
  limits = c(
    "87420130",
    "87332500",
    
    "87420150",
    "87420350",
    "87420500",
    "87510010"
  ),
  labels = c(
    "PM1", "PM2", "PM3", "PM4", "PM5", "PM6"
  )
)+


“Ok mas… e se eu não quiser alterar o código ottobacias para PM1, PM2, só a ordem das estações, o que devo fazer?” Basta replicar a sequência correta das estações de limits = c() dentro da função labels = c().

   scale_x_discrete(
     limits = c(
       "87420130",
       "87332500",
       "87420150",
       "87420350",
       "87420500",
       "87510010"
     ),
     labels = c(
       "87420130",
       "87332500",
       "87420150",
       "87420350",
       "87420500",
       "87510010"
     )
   )+


Obs: Para a Bacia Hidrográfica do Rio Gravataí esse processo é necessário.

Sempre tomar cuidado com os limites do eixo y. Deixei como padrão o R buscar automaticamente qual o valor mínimo e máximo daquele parâmetro, mas o ideal é que se ajuste caso a caso.

Caso queira alterar o tamanho dos outliers, alterar o size nesse trecho dos códigos:

ggbeeswarm::geom_quasirandom(
     # grouponX = FALSE,
     size = 1.2, 
     alpha = .25,
     width = .07,
   )+

Todos os gráficos foram gerados utilizando como padrão os limites da Resolução nº 357/05 do CONAMA para ambientes lóticos. Caso queira alterar os limites para adequar aos ambientes lênticos, deve-se editar os ymin e ymax de cada retângulo (rect) do referido parâmetro.

Não esquecer que o R entende a casa decimal como ponto, e não como vírgula.

annotate("rect",
         xmin = -Inf, xmax = Inf,
         ymin = 13.3, ymax = Inf,
         alpha = 1,
         fill = "#ac5079")+ #>pior classe
annotate("rect",
         xmin = -Inf, xmax = Inf,
         ymin = 3.7, ymax = 13.3,
         alpha = 1,
         fill = "#fcf7ab")+ #classe 3
annotate("rect",
         xmin = -Inf, xmax = Inf,
         ymin = 0, ymax = 3.7,
         alpha = 1,
         fill = "#8dcdeb")+ #classe 1

7.2 Parâmetros de Qualidade da Água

7.2.1 Oxigênio Dissolvido

(graf_od <- plan_litoral_medio %>%
   ggplot(
     aes(
       x = cod_estacao,
       y = oxigenio_dissolvido,
     )
   )+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = -Inf, ymax = 2,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 2, ymax = 4,
            alpha = 1,
            fill = "#eb5661")+ #classe 4
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 4, ymax = 5,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 5, ymax = 6,
            alpha = 1,
            fill = "#70c18c")+ #classe 2
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin= 6, ymax = Inf,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_summary(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_summary(
     fun.data = f,
     geom = "boxplot",
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(
     title = "Oxigênio Dissolvido",
     x= NULL,
     y="mg/L"
   )+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   scale_y_continuous(
     expand = expansion(mult = c(0,0)),
     n.breaks = 11,
     # limits = c(-0.3,21)
     limits = c(
       min(plan_litoral_medio$oxigenio_dissolvido, na.rm = TRUE),
       max(plan_litoral_medio$oxigenio_dissolvido, na.rm = TRUE)+1)
   )+
   # scale_x_discrete(
   #   limits = c(
   #     "87332500",
   #     "87420130",
   #     "87420150",
   #     "87420350",
   #     "87420500",
   #     "87510010"
   #   ),
   #   labels = c(
   #     "PM1", "PM2", "PM3", "PM4", "PM5", "PM6"
   #   )
   # )+
   geom_smooth(
     method = "lm",
     se = FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
     aes(group = 1),
     alpha = 0.5,
     na.rm = TRUE,
     size = 1
   )+
   theme_grafs()
)

Oxigênio Dissolvido

7.2.2 DBO

(graf_dbo <- ggplot(plan_litoral_medio,
                    aes(x = cod_estacao,
                   y = dbo))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 10, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 5, ymax = 10,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 3, ymax = 5,
            alpha = 1,
            fill = "#70c18c")+ #classe 2
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 3,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_summary(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_summary(
     fun.data = f,
     geom = "boxplot",
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(title = "Demanda Bioquímica de Oxigênio",
        x="Estação",
        y="mg/L")+
   ggbeeswarm::geom_quasirandom(
     # grouponX = FALSE,
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   scale_y_continuous(expand = expansion(mult = c(0.03,0.03)),
                      n.breaks = 8,
                      limits = c(
                        min(plan_litoral_medio$dbo, na.rm = TRUE),
                        10
                        # max(plan_litoral_medio$dbo, na.rm = TRUE)
                        ),
                      trans = "log10")+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

Demanda Bioquímica de Oxigênio

7.2.3 Escherichia coli

(graf_ecoli <- plan_litoral_medio %>% 
   ggplot(aes(cod_estacao,
              e_coli))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 3200, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 800, ymax = 3200,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 160, ymax = 800,
            alpha = 1,
            fill = "#70c18c")+ #classe 2
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 160,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_summary(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_summary(
     fun.data = f,
     geom = "boxplot",
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(title = "*Escherichia coli*",
        x="Estação",
        y="NMP/100mL")+
   scale_y_continuous(expand = expansion(mult = c(0.01, 0.01)),
                      # n.breaks = 9,
                      n.breaks = 6,
                      limits = c(min(plan_litoral_medio$e_coli, na.rm = TRUE),
                                 max(plan_litoral_medio$e_coli, na.rm = TRUE)),
                      trans = "log10",
                      labels = scales::number_format(accuracy = 1,
                                                     decimal.mark = ",",
                                                     big.mark = " "))+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
 # scale_x_discrete(limits = c("87398500",
 #                             "87398980",
 #                             "87398900",
 #                             "87398950",
 #                             "87405500",
 #                             "87406900",
 #                             "87409900"),
 #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
 # )+
 geom_smooth(method = "lm",
 se=FALSE, #stardand error = desvio padrão -> se deixar TRUE gera o intervalo de confiança de 95%
             aes(group=1),
             alpha= 0.5, #transparencia de 50%
             na.rm = TRUE, #remover NAs
             size = 1)+
 theme_grafs()+
   theme(
     axis.text.y = element_text(
       angle = 90,
       # size=15,
       # face=2
     ),
     plot.title = 
       element_markdown(
         hjust = 0.5,
         color = "black",
         size = 19),
   )
)

Escherichia-coli

7.2.4 Fósforo Total

(graf_ptot <- ggplot(plan_litoral_medio,
                     aes(cod_estacao,
                         fosforo_total))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0.15, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0.1, ymax = 0.15,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 0.1,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_summary(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_summary(
     fun.data = f,
     geom = "boxplot",
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(title = "Fósforo total",
        x="Estação",
        y="mg/L")+
   scale_y_continuous(expand = expansion(mult = c(0.03,0.03)),
                      n.breaks = 8,
                      limits = c(min(plan_litoral_medio$fosforo_total, na.rm = TRUE),
                                 max(plan_litoral_medio$fosforo_total), na.rm = TRUE),
                      trans = "log10",
                      labels = scales::number_format(accuracy = .001,
                                                     decimal.mark = ",",
                                                     big.mark = " ")
   )+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

Fósforo total

7.2.5 Nitrogênio amoniacal

(graf_namon <- ggplot(plan_litoral_medio,
                 aes(cod_estacao,
                     nitrogenio_amoniacal))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 13.3, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 3.7, ymax = 13.3,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 3.7,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_summary(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_summary(
     fun.data = f,
     geom = "boxplot",
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(title = "Nitrogênio amoniacal",
        x="Estação",
        y="mg/L")+
   scale_y_continuous(expand = expansion(mult = c(0.01, 0.05)),
                      n.breaks = 9,
                      limits = c(min(plan_litoral_medio$nitrogenio_amoniacal, na.rm = TRUE),
                                 15
                                 # max(plan_litoral_medio$nitrogenio_amoniacal, na.rm = TRUE)
                                 ),
                      trans = "log10",
                      labels = scales::number_format(accuracy = .001,
                                                     decimal.mark = ",",
                                                     big.mark = " "))+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

Nitrogênio Amoniacal

7.2.6 Turbidez

(graf_turb <- ggplot(plan_litoral_medio,
                   aes(cod_estacao,
                       turbidez))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 100, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 40, ymax = 100,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 40,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_summary(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_summary(
     fun.data = f,
     geom = "boxplot",
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(title = "Turbidez",
        x="Estação",
        y="UNT")+
   scale_y_continuous(expand = expansion(mult = c(0.05, 0.05)),
                      n.breaks = 8,
                      limits = c(
                        # 1,
                        min(plan_litoral_medio$turbidez, na.rm = TRUE),
                        # 500
                        max(plan_litoral_medio$turbidez, na.rm = TRUE)
                      ),
                      trans = "log10",
                      labels = scales::number_format(accuracy = 1,
                                                     decimal.mark = ",",
                                                     big.mark = " "))+
    ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

turbidez

7.2.7 pH

(graf_pH <- ggplot(plan_litoral_medio,
                 aes(cod_estacao,
                     ph))+
   annotate("rect",
            xmin=-Inf,
            xmax=Inf,
            ymin=-Inf,
            ymax=6,
            alpha=1,
            fill="#eb5661")+ #classe 4
   annotate("rect",
            xmin=-Inf,
            xmax=Inf,
            ymin=9,
            ymax=Inf,
            alpha=1,
            fill="#eb5661")+ #classe 4
   annotate("rect",
            xmin=-Inf,
            xmax=Inf,
            ymin=6,
            ymax=9,
            alpha=1,
            fill="#8dcdeb")+ #classe 1
   stat_summary(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_summary(
     fun.data = f,
     geom = "boxplot",
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(title = "pH",
        x="Estação",
        y="")+
   scale_y_continuous(expand = expansion(mult = c(0.01, 0.01)),
                      n.breaks = 8,
                      limits = c(4,11),
                      labels = scales::number_format(accuracy = 1,
                                                     decimal.mark = ",",
                                                     big.mark = " ")
                      )+
    ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

pH

7.2.8 Sólidos Totais

O parâmetro Sólidos Totais não teve medições no período analisado, então fica armazenado na tabela como valor vazio, ou rNA`.

# (graf_solidos_totais <- ggplot(plan_litoral_medio,
#                                aes(cod_estacao,
#                                    solidos_totais))+
#    annotate("rect",
#             xmin = -Inf, xmax = Inf,
#             ymin = 500, ymax = Inf,
#             alpha = 1,
#             fill="#ac5079")+ #>pior classe
#    annotate("rect",
#             xmin = -Inf, xmax = Inf,
#             ymin = -Inf, ymax = 500,
#             alpha = 1,
#             fill="#8dcdeb")+ #classe 1
# stat_summary(
#      fun.data = f,
#      geom = 'errorbar',
#      width = 0.3,
#      position = position_dodge(width = 0.65),
#    )+
#    stat_summary(
#      fun.data = f,
#      geom = "boxplot",
#      width = 0.7,
#      fill = '#F8F8FF',
#      color = "black",
#      outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
#    )+
#    # facet_wrap(~periodo)+
#    labs(title = "Sólidos totais",
#         x="Estação",
#         y="")+
#    scale_y_continuous(expand = expansion(mult = c(0.01, 0.05)),
#                       n.breaks = 8,
#                       limits = c(0,
#                                  max(plan_litoral_medio$solidos_totais, na.rm = TRUE)
#                                  ),
#                       labels = scales::number_format(accuracy = 1,
#                                                      decimal.mark = ",",
#                                                      big.mark = " "))+
#    ggbeeswarm::geom_quasirandom(
#      size = 1.2,
#      alpha = .25,
#      width = .07,
#    )+
#    # scale_x_discrete(limits = c("87398500", 
#    #                             "87398980", 
#    #                             "87398900", 
#    #                             "87398950", 
#    #                             "87405500", 
#    #                             "87406900", 
#    #                             "87409900"),
#    #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
#    # )+
#    geom_smooth(method = "lm",
#                se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
#                aes(group=1),
#                alpha=.5,
#                na.rm = TRUE,
#                size = 1)+
#    theme_grafs()
# )

7.2.9 Condutividade

(graf_cond_elet <- ggplot(plan_litoral_medio,
                          aes(cod_estacao,
                              condutividade))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 500, ymax = Inf,
            alpha = 1,
            fill = "#eb5661")+ #classe 4
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 500,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
  stat_summary(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_summary(
     fun.data = f,
     geom = "boxplot",
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(title = "Condutividade elétrica",
        x="Estação",
        y="µmhos/cm")+
   scale_y_continuous(expand = expansion(mult = c(0.05, 0.05)),
                      n.breaks = 8,
                      limits = c(min(plan_litoral_medio$condutividade, na.rm = TRUE),
                                 max(plan_litoral_medio$condutividade, na.rm = TRUE)),
                      trans = "log10",
                      labels = scales::number_format(accuracy = 1,
                                                     decimal.mark = ",",
                                                     big.mark = " "))+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()+
   theme(
     axis.text.y = element_text(
       angle = 90,
       # size=15,
       # face=2
     )
   )
)

condutividade-eletrica

7.3 Análise ao longo do tempo

Para gerar um gráfico ao longo do tempo pra cada uma das estações é necessário alterar o ano_inicial e o ano_final. Também é necessário selecionar qual parâmetro que se quer fazer a visualização.

ano_inicial <- 2015
ano_final <- 2022

(timeline <- plan_litoral_medio %>%
  filter(ano_coleta > ano_inicial &
           ano_coleta <= ano_final) %>%
  dplyr::select(cod_estacao, e_coli, data_coleta) %>%
  group_by(cod_estacao) %>%
  ggplot(
    aes(x = data_coleta,
        y = e_coli,
        color = cod_estacao
    ))+
    geom_line(
      # aes(color = CODIGO),
      na.rm = TRUE)+
    geom_point(
      # aes(color = CODIGO),
      na.rm = TRUE)+
    scale_x_date(
      limits = as.Date(c(
        ymd(glue("{ano_inicial}-01-01")),
        ymd(glue("{ano_final}-01-01"))
        # NA #pode usar NA também
      )),
      expand = c(0.0, 0.0),
      date_breaks = "2 years",
      minor_breaks = "1 years",
      date_labels = "%Y",
    )+
  # geom_smooth(
  #   method = "lm", #regressao linear
  #   se = TRUE, #se deixar TRUE gera o intervalo de confiança de 95%
  #   aes(group = 1),
  #   alpha =.5,
  #   na.rm = TRUE,
  #   size = 0.3,
  #   # fullrange = TRUE,
  #   show.legend = TRUE
  # )+
  stat_smooth(
    geom = "smooth",
    # span = 0.2,
    se = TRUE, #se deixar TRUE gera o intervalo de confiança de 95%
    # aes(group = 1),
    # alpha =.5,
    na.rm = TRUE,
    # size = 0.3,
    fullrange = TRUE,
    show.legend = TRUE
  )+
  facet_wrap(
    ~cod_estacao,
    nrow = 4,
  )+
  theme_bw()
)

7.4 Correlação

parametros_iqa_lit_medio <- plan_litoral_medio %>%
  dplyr::select(cod_estacao,
         ph,
         dbo,
         e_coli,
         nitrogenio_amoniacal,
         # nitro_kjeldahl,
         # nitro_total,
         fosforo_total,
         temperatura_da_agua,
         turbidez,
         solidos_totais,
         oxigenio_dissolvido,
         condutividade,
         ano_coleta
         ) 

parametros_iqa_lit_medio %>% 
  dplyr::select(
    -cod_estacao,
    -ano_coleta,
    -solidos_totais
    ) %>%
  # group_by(cod_estacao) %>%
  rename(
    CE = condutividade,
    OD = oxigenio_dissolvido,
    # ST = solidos_totais,
    Turb = turbidez,
    Temp = temperatura_da_agua,
    Ptot = fosforo_total,
    NAmon = nitrogenio_amoniacal,
    pH = ph,
    DBO = dbo,
    E_coli = e_coli
    # NTK = nitro_kjeldahl
  ) %>% 
  ggcorr(
    method =
    "complete.obs",
    # "pearson",
    # "pairwise",
    name = "Correlação",
    label = TRUE,
    label_alpha = TRUE,
    digits = 3,
    low = "#3B9AB2",
    mid = "#EEEEEE",
    high = "#F21A00",
    # palette = "RdYlBu",
    layout.exp = 0,
    legend.position = "left",
    label_round = 3,
    # legend.size = 18,
    geom = "tile",
    nbreaks = 10,
  )+
  labs(title = "Correlação entre parâmetros físico-químicos na\nBacia Hidrográfica do Litoral Médio")+
  theme_linedraw()+
  theme(
    legend.position = c(0.15, 0.6),
    legend.title = element_text(size = 16),
    legend.text = element_text(size = 14),
    # legend.spacing = unit(element_text(),
                          # units = 5)
    plot.title = element_text(hjust = 0.5,
                              size = 16)
  )

correlação-parametros-qualidade-agua

7.4.1 Correlação entre parâmetros que compõem o IQA com significância estatística

# Gráfico das correlações entre todos os parâmetros com significância
correl_IQA_lit_medio <- parametros_iqa_lit_medio %>%
  dplyr::select(-cod_estacao) %>%
  ggpairs(title = "Correlação entre parâmetros que compõem o IQA",
          axisLabels = "show")
# correl_IQA_lit_medio

7.5 Salvar os gráficos

Replicar esse modelo pros gráficos que deseja salvar.
1. Criar novo code chunk (Ctrl+Alt+I)
2. Copiar a fórmula abaixo
3. Colar nesse novo code chunk
4.

Os gráficos ficarão salvos em uma pasta que irá ser criada a partir do código.

ggsave("graf_od.png",
       plot = graf_od, #alteracao
       path = "./graficos",
       dpi = 300,
       type = "cairo")

8 Mapas

8.1 Pacotes pra geração de mapas

pacman::p_load(raster, leaflet, sf
               # prettymapr, rjson, rosm,
               # ggspatial
               # rgdal, rgeos,
               # gtools, tidyverse, rnaturalearth,
               # rnaturalearthdata, reticulate, maptools,
               # maps, ggplot2, ggspatial, rgeos, ggmap
               )

8.2 Mapa estático

Importando as informações necessárias pra gerar mapas de precipitação.
Fonte: GADM 1, 2

Brasil <- getData(
  'GADM',
  country = 'Brazil',
  level = 3
) %>%
  st_as_sf()
## Warning in getData("GADM", country = "Brazil", level = 3): getData will be removed in a future version of raster
## . Please use the geodata package instead
RS <- subset(Brasil,
             NAME_1 == "Rio Grande do Sul")

lbl <- data.frame(month_abb = month.abb,
                  mes = 1:12)

plan_litoral_medio %>%
  ggplot(
    # aes(x = longtitude,
    #     y = latitude,
    #     map_id = region)
  )+
  geom_sf(
    data = RS
  )+
  theme_bw()
plot

Mapa estático do RS

# Definindo o SRC
RS <- RS %>%
  st_transform (crs = 4674) #4326 = WGS84, 4674 = SIRGAS2000

8.3 Mapa interativo com localização dos pontos de monitoramento

leaflet(RS) %>% 
  addProviderTiles(
    "Esri.WorldImagery" #Imagem de satélite
    # "OpenStreetMap.Mapnik" #OpenStreetMap -> Software livre
  ) %>% 
  addCircleMarkers(
    data = plan_litoral_medio,
    lng = ~longitude,
    lat = ~latitude,
    popup = ~paste(
      "<b>Estação:</b>",{cod_estacao},"<br>",
      "<b>Recurso hídrico:</b>", recurso_hidrico, "<br>",
      "<b>Município:</b>", municipio,
      sep = " "
    )
  ) 

Mapa interativo

8.4 Mapa de precipitação anual

# st_centroid(RS)
# 
# Prec <- getData(
#   "worldclim", 
#   var = "prec", 
#   res = 0.5, 
#   lat = c(-30.033056, -29.68417), #procurar lat long no google e alterar aqui
#   lon = c(-51.230000, -53.80694)
# )
# 
# Prec_RS <- Prec %>% 
#   crop(RS) %>% 
#   mask(RS, na.rm = TRUE)
# 
# plot(Prec_RS)
# 
# PPAnual_RS <- do.call("sum", 
#                        unstack(Prec_RS))
# plot(PPAnual_RS)
# vls <- rasterToPoints(Prec_RS) %>% 
#   as_tibble() %>% 
#   gather(var, value, -x, -y) %>% 
#   mutate(mes = parse_number(var)) %>% 
#   inner_join(., lbl, by = 'mes') %>% 
#   dplyr::select(x, y, month_abb, value) %>% 
#   mutate(month_abb = factor(month_abb, levels = month.abb))
# 
# vls %>% 
#   filter(month_abb == 'Jan')
# 
# summary(vls$value) #descobre o valor mínimo, médio e máximo de precipitação

8.5 Mapa com precipitação mensal

Caso queira gerar um mapa com a precipitação mensal, alternar o include para TRUE. A geração desse mapa demanda bastante processamento, recomendável manter include = FALSE e echo = FALSE.

Ainda precisa ser implementado/ajustado

  • RSÁgua deve buscar dados anteriores a 2015.
  • A Fepam tem os dados de altitude das estações. A partir disso pode ser calculado o % de saturação de Oxigênio Dissolvido, necessário para o cálculo do IQA.
  • Tornar a coluna de chuva_24h como factor.
  • A coluna hora_coleta está com formato incorreto.
  • Gerar um Shiny Web App
  • Tornar a coluna de municipio com apenas a primeira letra maiúscula.
  • Sincronização via GitHub
  • Aprender a gerar o mapa de precipitação mensal pra todo o RS
    • O RS está entre 2 fusos, então acaba “partindo no meio” a figura
  • Futuramente: integração via Google Sheets.

Informações adicionais

E-mail para contato: leonardofwink@gmail.com

GitHub: https://github.com/leonardofwink/

LinkedIn: https://www.linkedin.com/in/leonardofwink/

LS0tDQp0aXRsZTogIlR1dG9yaWFsIC0gY29tbyBnZXJhciBvcyBncsOhZmljb3MgYm94cGxvdCBubyBSIGEgcGFydGlyIGRvIFJTw4FndWEgLSBGZXBhbSINCmF1dGhvcjogIkxlb25hcmRvIEZlcm5hbmRlcyBXaW5rIg0KZW1haWw6ICJsZW9uYXJkb2Z3aW5rQGdtYWlsLmNvbSINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkLyVtLyVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRpc3RpbGw6OmRpc3RpbGxfYXJ0aWNsZToNCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sNCiAgICBrZWVwX21kOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KICAgICAgc21vb3RoX3Njcm9sbDogbm8NCiAgICB0aGVtZTogZmxhdGx5DQogICAgZmlnX3dpZHRoOiAxMA0KICAgIGZpZ19oZWlnaHQ6IDYuNjYNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIGtlZXBfbWQ6IHllcw0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgZ2l0aHViX2RvY3VtZW50Og0KICAgIGh0bWxfcHJldmlldzogdHJ1ZQ0KYWx3YXlzX2FsbG93X2h0bWw6IHllcw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KZmlnLmFsaWduOiBjZW50ZXINCi0tLQ0KDQojIFByaW1laXJvIGFjZXNzbyB7I3NlYy1wcmltZWlyby1hY2Vzc28gLnVubnVtYmVyZWR9DQoNCk9sw6EhIE5lc3NlIHR1dG9yaWFsIHZvY8OqIGlyw6EgYXByZW5kZXIgYSByZXBsaWNhciB0dWRvIHF1ZSBzZXLDoSBleGliaWRvIG5lc3NhIHDDoWdpbmEhXA0KDQpQYXJhIGlzc28sIHZvY8OqIHByZWNpc2EgdGVyIGluc3RhbGFkbyBlbSBzZXUgY29tcHV0YWRvciAyIHByb2dyYW1hczogbyBgUmAgZSBvIGBSU3R1ZGlvYC5cDQpPIFIgw6kgYSBsaW5ndWFnZW0gZGUgcHJvZ3JhbWHDp8OjbyBlIG8gUlN0dWRpbyBhIGludGVyZmFjZSBncsOhZmljYSwNCg0KVm9jw6ogcG9kZSBiYWl4YXIgbyBgUmAgZSBvIGBSU3R1ZGlvYCBhdHJhdsOpcyBkbyBsaW5rIDxodHRwczovL3Bvc2l0LmNvL2Rvd25sb2FkL3JzdHVkaW8tZGVza3RvcC8+XA0KDQoxLiAgU2Ugw6kgbyBzZXUgcHJpbWVpcm8gYWNlc3NvLCBjbGlxdWUgbmEgY2FpeGluaGEgYENvZGVgIG5vIGNhbnRvIHN1cGVyaW9yIGRpcmVpdG8gcGFyYSBiYWl4YXIgbyBjw7NkaWdvIG5vIGZvcm1hdG8gYC5SbWRgLCBvdSBzZWphLCBSTWFya2Rvd24uDQoyLiAgQWJyYSBvIFJTdHVkaW8NCjMuICBDbGlxdWUgZW0gRmlsZSAtXD4gT3BlbiBmaWxlIC1cPiBlIHNlbGVjaW9uZSBlc3NlIGFycXVpdm8gYC5SbWRgIHF1ZSB2b2PDqiBiYWl4b3UuDQo0LiAgVm9jw6ogZGV2ZSBjaGVnYXIgYSB1bWEgdGVsYSBzZW1lbGhhbnRlIGEgZGEgZmlndXJhIGFiYWl4bw0KDQohW10oaW1hZ2VzLzIwMjIxMjI3LTA0MDcyNi0wMDMucG5nKQ0KDQpOYSBwcmltZWlyYSB2ZXogZW0gcXVlIGZvciByb2RhciBvcyBjw7NkaWdvcyBhcXVpIG5vIFIsIHNlcsOhIHNvbGljaXRhZG8gcXVlIGluc3RhbGUgcGFjb3Rlcy4gUXVhbmRvIGFwYXJlY2VyZW0gY2FpeGFzIGRlIGRpw6Fsb2dvLCBjbGlxdWUgZW0gKipgWWVzYCoqLg0KDQpQb2RlIGRlbW9yYXIgdW0gcG91Y28gZXNzZSBwcm9jZXNzby4gUGFyYSB0ZXIgdW1hIG1lbGhvciB2aXN1YWxpemHDp8OjbyBkZXNzZSB0dXRvcmlhbCBwcmVzc2lvbmUgYXMgdGVjbGFzIGBDdHJsK1NoaWZ0K0tgIG91IGNsaXF1ZSBubyBib3TDo28gYEtuaXRgIGFjaW1hLiBSZWNvbWVuZG8gbWFudGVyIHVtYSBhYmEgZG8gbmF2ZWdhZG9yIGNvbSBvIGFycXVpdm8gYHR1dG9yaWFsX1IuaHRtbGAgYWJlcnRvLg0KDQpKw6EgcG9kZW1vcyByb2RhciBvIGPDs2RpZ28gcGVsYSBwcmltZWlyYSB2ZXohXA0KUGFyYSBpc3NvLCBhcGVydGUgYEN0cmwrQWx0K1JgIG91IGNsaXF1ZSBlbSBgUnVuYCBubyBtZW51IHN1cGVyaW9yIGUgZGVwb2lzIGVtIGBSdW4gQWxsYDpcDQohW10oaW1hZ2VzLzIwMjIxMjI3LTAzNTU0My0wMDEucG5nKQ0KDQpFbnF1YW50byBvcyBwYWNvdGVzIGVzdMOjbyBzZW5kbyBpbnN0YWxhZG9zLCBwcm9zc2lnYSBjb20gYSBsZWl0dXJhLiBEZWl4ZWkgYWxndW5zIGNvbnRlw7pkb3MgbmFzIFtSZWZlcsOqbmNpYXNdKCNzZWMtbGlua3Mtw7p0ZWlzKSBxdWUgaXLDo28gY29tcGxlbWVudGFyIGVzc2UgZG9jdW1lbnRvLg0KDQpRdWFuZG8gcXVpc2VyIHJlbmRlcml6YXIgbyBjw7NkaWdvIHBhcmEgdGVyIGEgbWVzbWEgdmlzdWFsaXphw6fDo28gY29tbyBhIGRvIGZvcm1hdG8gYC5odG1sYCB1c2UgbyBjb21hbmRvIGRlIGBLbml0YCwgbyBgQ3RybCtTaGlmdCtLYCwgb3UgY2FzbyBlc3RlamEgY29tIHVtIGdyw6FmaWNvIGFiZXJ0bywgY2xpcXVlIGVtIFZpZXdlciBuYSBqYW5lbGEgaW5mZXJpb3IgZGlyZWl0YS4NCg0KIVtdKGltYWdlcy9wYXN0ZS0xOTdGQ0FGQS5wbmcpDQoNCiMgQ29tYW5kb3MgbWFpcyB1dGlsaXphZG9zIHsjc2VjLWNvbWFuZG9zLW1haXMtdXRpbGl6YWRvc30NCg0KYEN0cmwrQWx0K1JgIC1cPiBleGVjdXRhIFRPRE9TIG9zIGPDs2RpZ29zIGRlIHVtYSB2ZXogc8OzLg0KDQpgS25pdGAgb3UgYEN0cmwrU2hpZnQrS2AgLVw+IHJvZGEgVE9ET1Mgb3MgY8OzZGlnb3MgZGUgdW1hIHZleiBzw7MgZSByZW5kZXJpemEgYSB2aXN1YWxpemHDp8OjbyBlbSBmb3JtYXRvcyBgLmh0bWxgIG91IGAucGRmYC4NCg0KYEN0cmwrRW50ZXJgIC1cPiBleGVjdXRhIHVtICJwYXLDoWdyYWZvIiBkZSBjw7NkaWdvcy4NCg0KYEFsdCtFbnRlcmAgLVw+IGV4ZWN1dGEgbyAicGFyw6FncmFmbyIgZGUgY8OzZGlnb3MgbWFzIHNlbSBtb3ZlciBvIGN1cnNvci4NCg0KYEN0cmwrU2hpZnQrQ2AgLVw+IHBhcmEgY29tZW50YXIgb3UgKmRlc2NvbWVudGFyKiB1bSBpbnRlcnZhbG8gZGUgbGluaGFzLg0KDQo+IEFzIGxpbmhhcyBkZSBjw7NkaWdvIHF1ZSBjb21lw6dhbSBjb20gYCNgIHPDo28gKipjb21lbnTDoXJpb3MqKi4gRWxhcyBuw6NvIGltcGFjdGFtIG8gcmVzdWx0YWRvIGZpbmFsIGRvIGPDs2RpZ28uDQoNCmBDdHJsK0FsdCtJYCAtXD4gY3JpYSB1bSBub3ZvICpjb2RlIGNodW5rKi4NCg0KYEN0cmwrSWAgLVw+IEluZGVudGEgbyBjw7NkaWdvIChhanVzdGEgYSB0YWJ1bGHDp8OjbyBlbnRyZSBhcyBsaW5oYXMsIGZhY2lsaXRhIGEgbGVpdHVyYSBkbyBjw7NkaWdvKS4NCg0KPiBBIGxpc3RhIGNvbXBsZXRhIGRlIGF0YWxob3MgcG9kZSBzZXIgY29uZmVyaWRhIG5vIG1lbnUgc3VwZXJpb3IgVG9vbHMgLVw+IEtleWJvYXJkIFNob3J0Y3V0cyBIZWxwLCBvdSBhdHJhdsOpcyBkbyBhdGFsaG8gYEFsdCtTaGlmdCtLYC4NCg0KIyBQYXNzby1hLXBhc3NvIHsjc2VjLXBhc3NvLWEtcGFzc299DQoNCj4gKipJbXBvcnRhbnRlKio6IENvbSBlc3NlIGFycXVpdm8gYC5SbWRgIHZvY8OqIGRldmUgY2hlZ2FyIGFvcyBtZXNtb3MgcmVzdWx0YWRvcyBxdWUgcHJlc2VudGVzIG5vIGFycXVpdm8gYHR1dG9yaWFsX1IuaHRtbGAuDQo+DQo+IFZvdSBkZWl4YXIgY29tZW50YWRvIG9zIHBlZGHDp29zIGRlIGPDs2RpZ28gcXVlIG5lY2Vzc2l0YW0gZGUgYWx0ZXJhw6fDo28gb2JyaWdhdMOzcmlhIGNvbSBhIG5vbWVuY2xhdHVyYSBgYWx0ZXJhY2FvX2Agc2VndWlkbyBkZSB1bSBuw7ptZXJvLg0KPg0KPiBQYXJhIGVuY29udHJhciBmYWNpbG1lbnRlIG9zIGxvY2FpcyBxdWUgcHJlY2lzYW0gc2VyIGFqdXN0YWRvcywgYmFzdGEgdXRpbGl6YXIgbyBjb21hbmRvIGBDdHJsK0ZgIGUgcHJvY3VyYXIgcG9yIGBhbHRlcmFjYW9fYCBlIG8gcmVzcGVjdGl2byBuw7ptZXJvIGxpc3RhZG8gYWJhaXhvLg0KDQoxLiAgUmVub21lYXIgYSBwbGFuaWxoYSBhIHNlciBpbXBvcnRhZGEgcHJhIGZhY2lsaXRhciBhIGxlaXR1cmEuDQogICAgLSAgIG5lc3NlIGNhc28gcmVub21lZWkgYSBwbGFuIGdlcmFkYSBwZWxvIFJTw4FndWEgZGUgYERhZG9zXzIwMjIxMjIyMTQzMzA1Lnhsc2AgcGFyYSBgcGxhbl9saXRvcmFsX21lZGlvLnhsc2AuDQogICAgLSAgIHZvY8OqIHBvZGUgdXNhciBgQ3RybCtGYCBlIHN1YnN0aXR1aXIgdG9kYXMgYXMgb2NvcnLDqm5jaWFzIGRlIGBwbGFuX2xpdG9yYWxfbWVkaW9gIHBhcmEgbyBub21lIHF1ZSB2b2PDqiBkZXUgw6AgcGxhbmlsaGEuDQoyLiAgQWp1c3RhciBvIGNhbWluaG8gZG8gYXJxdWl2by4gKCoqYWx0ZXJhY2FvXzEqKikNCiAgICAtICAgbmVzc2UgZXhlbXBsbyBlc3RvdSBpbXBvcnRhbmRvIGRpcmV0YW1lbnRlIGRhIHBhc3RhIGRlIGRvd25sb2FkcyBkbyBtZXUgY29tcHV0YWRvcjogYCJDOi9Vc2Vycy9Mw6lvL0Rvd25sb2Fkcy9wbGFuX2xpdG9yYWxfbWVkaW8ueGxzImANCiAgICAtICAgRnV0dXJhbWVudGUgcXVlcm8gaW1wbGVtZW50YXIgYSBpbnRlZ3Jhw6fDo28gY29tIG8gW0dvb2dsZSBTaGVldHNdKCNzZWMtYWluZGEtcHJlY2lzYS1zZXItaW1wbGVtZW50YWRvKS4NCjMuICBWZXJpZmljYXIgbyBpbnRlcnZhbG8gZGUgZGFkb3MgZGEgcGxhbmlsaGEuIEFzIMO6bHRpbWFzIDEwIGxpbmhhcyBjb3N0dW1hbSBzZXIgZG9zIHN1bcOhcmlvcywgbWFzIG8gUiBuw6NvIGVudGVuZGUgaXNzby4NCiAgICAtICAgdmVyaWZpY2FyIGF0w6kgcXVhbCBsaW5oYSBhIGNvbHVuYSBgw41uZGljZWAgdGVtIHZhbG9yZXMgcmVnaXN0cmFkb3MsIG5lc3RlIGNhc28gbyBgw41uZGljZWAgdmFpIGF0w6kgOTggKCsxIGxpbmhhIGRlIGNhYmXDp2FsaG8pID0gbGluaGEgOTkNCiAgICAtICAgQWx0ZXJhciBuYSBwYXJ0ZSBkZSBpbXBvcnRhw6fDo28gbyBpbnRlcnZhbG8gcGFyYSBjb21wcmVlbmRlciBzb21lbnRlIG9zIGRhZG9zICgqKmFsdGVyYWNhb18yKiopDQogICAgLSAgIEVzdG91IHRlbnRhbmRvIGRlc2NvYnJpciBjb21vIGVjb25vbWl6YXIgZXNzYSBldGFwYS4NCg0KIyBQYWNvdGVzIG5lY2Vzc8OhcmlvcyB7I3NlYy1wYWNvdGVzLW5lY2Vzc8OhcmlvcyAucGFjb3Rlc30NCg0KYGBge3IgY29uZmlndXJhbmRvIGV4aWJpci9vY3VsdGFyIGPDs2RpZ28gZSByZXN1bHRhZG9zLCBpbmNsdWRlPUZBTFNFfQ0KaG9va3MgPSBrbml0cjo6a25pdF9ob29rcyRnZXQoKQ0KDQpob29rX2ZvbGRhYmxlID0gZnVuY3Rpb24odHlwZSkgew0KICBmb3JjZSh0eXBlKQ0KICBmdW5jdGlvbih4LCBvcHRpb25zKSB7DQogICAgcmVzID0gaG9va3NbW3R5cGVdXSh4LCBvcHRpb25zKQ0KICAgIA0KICAgIGlmIChpc0ZBTFNFKG9wdGlvbnNbW3Bhc3RlMCgiZm9sZC4iLCB0eXBlKV1dKSkgcmV0dXJuKHJlcykNCiAgICANCiAgICBwYXN0ZTAoDQogICAgICAiPGRldGFpbHM+PHN1bW1hcnk+IiwgdHlwZSwgIjwvc3VtbWFyeT5cblxuIiwNCiAgICAgIHJlcywNCiAgICAgICJcblxuPC9kZXRhaWxzPiINCiAgICApDQogIH0NCn0NCg0Ka25pdHI6OmtuaXRfaG9va3Mkc2V0KA0KICBvdXRwdXQgPSBob29rX2ZvbGRhYmxlKCJvdXRwdXQiKSwNCiAgcGxvdCA9IGhvb2tfZm9sZGFibGUoInBsb3QiKQ0KKQ0KDQojIERpc2FibGUgZm9sZGluZw0KDQojIGBgYHtyLCBmb2xkLm91dHB1dD1GQUxTRSwgZm9sZC5wbG90PUZBTFNFfQ0KIyBybm9ybSgxMCkNCiMgcGxvdChpcmlzKQ0KIyBgYGANCmBgYA0KDQpObyBgY29kZSBjaHVua2AgYWJhaXhvIHNlcsOjbyBpbnN0YWxhZG9zIHRvZG9zIG9zIHBhY290ZXMgbmVjZXNzw6FyaW9zLiBDYWRhIHBhY290ZSBjb250w6ltIGZ1bsOnw7VlcyBlc3BlY8OtZmljYXMgcXVlIGF1eGlsaWFtIG5vIGRlc2Vudm9sdmltZW50byBkYSBhdGl2aWRhZGUsIHNlamEgYSBpbXBvcnRhw6fDo28gZG8gZGFkbyAoYHJlYWRyYCwgYHJlYWR4bGApLCBuYSBtYW5pcHVsYcOnw6NvIGRvcyBkYWRvcyAobGltcGV6YS90cmF0YW1lbnRvIGNvbSBgamFuaXRvcmAgZSBgbHVicmlkYXRlYCksIG5hIHZpc3VhbGl6YcOnw6NvIChgZ2dwbG90MmAsIGBybWFya2Rvd25gLCBga2FibGVFeHRyYWApIG91IHByYSBwcmF0aWNhbWVudGUgdHVkbyAoYHRpZHl2ZXJzZWApLg0KDQpgYGB7ciBQYWNvdGVzIG5lY2Vzc8OhcmlvcywgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gVFJVRX0NCnBhY21hbjo6cF9sb2FkKA0KICAjIEVUTCAoZXh0cmFjdCwgdHJhbnNmb3JtLCBsb2FkKQ0KICBqYW5pdG9yLCByZWFkciwgcmVhZHhsLCBsdWJyaWRhdGUsDQogIGRwbHlyLCANCiAgdGlkeXZlcnNlLCANCiAgZ2x1ZSwNCiAgIyBWaXN1YWxpemHDp8Ojbw0KICBnZ3Bsb3QyLA0KICBHR2FsbHksIA0KICBybWFya2Rvd24sIA0KICBrbml0ciwNCiAga2FibGVFeHRyYSwNCiAgZ2diZWVzd2FybSwgDQogIGdndGV4dA0KICAjIGJvb2tkb3duDQopDQojZ29vZ2xlc2hlZXRzNA0KYGBgDQoNClBhcmEgYWNlc3NhciBhIHDDoWdpbmEgZGUgYWp1ZGEgZG9zIHBhY290ZXMgb3UgZGFzIGZ1bsOnw7VlcywgYmFzdGEgdXNhciB1bSBgP2AgYW50ZXMgZG8gcXVlIHNlIGVzdMOhIGJ1c2NhbmRvLg0KDQpObyBleGVtcGxvIGFiYWl4byBlc3RvdSB2ZXJpZmljYW5kbyBvcyBhcmd1bWVudG9zIGRhIGZ1bsOnw6NvIGBwX2xvYWRgLCBkbyBwYWNvdGUgYHBhY21hbmAuIE5hIHNlcXXDqm5jaWEgYWJybyBvIG1lbnUgZGUgYWp1ZGEgZG8gcGFjb3RlIGB0aWR5dmVyc2VgLCB1bSBkb3MgbWFpcyBpbXBvcnRhbnRlcyBkYSBjb211bmlkYWRlIFIuIE91dHJhIG1hbmVpcmEgcG9zc8OtdmVsIHNlcmlhIHV0aWxpemFuZG8gYGhlbHAocGFja2FnZSA9ICdwYWNtYW4nKWAuDQoNCiFbP2hlbHBdKGltYWdlcy8yMDIyMTIyNy0xNjIzMzUtMDAyLnBuZykNCg0KIyBJbXBvcnRhw6fDo28gZG9zIGRhZG9zIHsjc2VjLWltcG9ydGHDp8Ojby1kb3MtZGFkb3N9DQoNCmBgYHtyIHJlcGxpY2FuZG8gaW1wb3J0YcOnw6NvIGRvcyBkYWRvcywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCnBsYW5fbGl0b3JhbF9tZWRpbyA8LSByZWFkX2RlbGltKA0KICAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2xlb25hcmRvZndpbmsvdHV0b3JpYWxfUl9mZXBhbS9tYWluL3BsYW5pbGhhX3JzYWd1YS9wbGFuX2xpdG9yYWxfbWVkaW8lMjAtJTIwRGFkb3NfQWp1c3RhZG9zLnRzdiIsIA0KICBkZWxpbSA9ICJcdCIsIA0KICBlc2NhcGVfZG91YmxlID0gRkFMU0UsDQogIGNvbF90eXBlcyA9IGNvbHMoDQogICAgw41ORElDRSA9IGNvbF9udW1iZXIoKSwNCiAgICBgQ8OTRC4gRVNUQcOHw4NPYCA9IGNvbF9jaGFyYWN0ZXIoKSwNCiAgICBMQVRJVFVERSA9IGNvbF9udW1iZXIoKSwNCiAgICBMT05HSVRVREUgPSBjb2xfbnVtYmVyKCksDQogICAgYEJBQ0lBIEhJRFJPR1LDgUZJQ0FgID0gY29sX2NoYXJhY3RlcigpLA0KICAgIGBSRUNVUlNPIEjDjURSSUNPYCA9IGNvbF9jaGFyYWN0ZXIoKSwNCiAgICBSRUdJw4NPID0gY29sX2NoYXJhY3RlcigpLA0KICAgIE1VTklDw41QSU8gPSBjb2xfY2hhcmFjdGVyKCksDQogICAgQU1CSUVOVEUgPSBjb2xfY2hhcmFjdGVyKCksDQogICAgYERBVEEgQ09MRVRBYCA9IGNvbF9kYXRlKGZvcm1hdCA9ICIlbS8lZC8lWSIpLA0KICAgIGBIT1JBIENPTEVUQWAgPSBjb2xfdGltZShmb3JtYXQgPSAiJUg6JU06JVMiKSwNCiAgICBgQ0hVVkEgMjRIYCA9IGNvbF9jaGFyYWN0ZXIoKSwNCiAgICBBTENBTElOSURBREUgPSBjb2xfbnVtYmVyKCksDQogICAgQUxVTcONTklPID0gY29sX251bWJlcigpLA0KICAgIEPDgURNSU8gPSBjb2xfbnVtYmVyKCksDQogICAgQ0hVTUJPID0gY29sX251bWJlcigpLA0KICAgIENMT1JFVE8gPSBjb2xfbnVtYmVyKCksDQogICAgYENMT1JPRklMQSBBYCA9IGNvbF9udW1iZXIoKSwNCiAgICBDT0JSRSA9IGNvbF9udW1iZXIoKSwNCiAgICBgQ09MSUZPUk1FUyBURVJNT1RPTEVSQU5URVNgID0gY29sX251bWJlcigpLA0KICAgIGBDT0xJRk9STUVTIFRPVEFJU2AgPSBjb2xfbnVtYmVyKCksDQogICAgQ09ORFVUSVZJREFERSA9IGNvbF9udW1iZXIoKSwNCiAgICBgQ1JPTU8gVE9UQUxgID0gY29sX251bWJlcigpLA0KICAgIGBERU1BTkRBIEJJT1FVw41NSUNBIERFIE9YSUfDik5JT2AgPSBjb2xfbnVtYmVyKCksDQogICAgYERFTUFOREEgUVXDjU1JQ0EgREUgT1hJR8OKTklPYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgRVNDSEVSSUNISUEgQ09MSWAgPSBjb2xfbnVtYmVyKCksDQogICAgRkVSUk8gPSBjb2xfbnVtYmVyKCksDQogICAgYEZJVE9QTEFOQ1RPTiAgLSBDSUFOT0JBQ1TDiVJJQVNgID0gY29sX251bWJlcigpLA0KICAgIGBGT1NGQVRPIE9SVE9gID0gY29sX251bWJlcigpLA0KICAgIGBGw5NTRk9STyBUT1RBTGAgPSBjb2xfbnVtYmVyKCksDQogICAgTUFOR0FOw4pTID0gY29sX251bWJlcigpLA0KICAgIGBNRVJDw5pSSU8gRU0gTUlDUk9HUkFNQSBQT1IgTElUUk8gKFVHL0wpYCA9IGNvbF9udW1iZXIoKSwNCiAgICBOw41RVUVMID0gY29sX251bWJlcigpLA0KICAgIE5JVFJBVE8gPSBjb2xfbnVtYmVyKCksDQogICAgYE5JVFJPR8OKTklPIEFNT05JQUNBTGAgPSBjb2xfbnVtYmVyKCksDQogICAgYE5JVFJPR8OKTklPIE9SR8OCTklDT2AgPSBjb2xfbnVtYmVyKCksDQogICAgYE5JVFJPR8OKTklPIFRPVEFMIEtKRUxEQUhMYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgT1hJR8OKTklPIERJU1NPTFZJRE9gID0gY29sX251bWJlcigpLA0KICAgIFBIID0gY29sX251bWJlcigpLA0KICAgIGBQUk9GVU5ESURBREUgQ09MRVRBYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgUFJPRlVORElEQURFIFRPVEFMYCA9IGNvbF9udW1iZXIoKSwNCiAgICBTQUxJTklEQURFID0gY29sX251bWJlcigpLA0KICAgIGBTw5NMSURPUyBESVNTT0xWSURPUyBUT1RBSVNgID0gY29sX251bWJlcigpLA0KICAgIGBTw5NMSURPUyBTVVNQRU5TT1MgVE9UQUlTYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgU8OTTElET1MgVE9UQUlTYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgVEVNUEVSQVRVUkEgREEgw4FHVUFgID0gY29sX251bWJlcigpLA0KICAgIGBURU1QRVJBVFVSQSBETyBBUmAgPSBjb2xfbnVtYmVyKCksDQogICAgYFRSQU5TUEFSw4pOQ0lBIERBIMOBR1VBYCA9IGNvbF9udW1iZXIoKSwNCiAgICBUVVJCSURFWiA9IGNvbF9udW1iZXIoKSwNCiAgICBgVkFaw4NPIFJFQ1VSU08gSMONRFJJQ09gID0gY29sX251bWJlcigpLA0KICAgIFpJTkNPID0gY29sX251bWJlcigpDQogICksDQogIGxvY2FsZSA9IGxvY2FsZSgNCiAgICBkYXRlX25hbWVzID0gInB0IiwgDQogICAgZGVjaW1hbF9tYXJrID0gIiwiLA0KICAgIGdyb3VwaW5nX21hcmsgPSAiIg0KICApLA0KICB0cmltX3dzID0gVFJVRQ0KKSAlPiUNCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUNCiAgc2xpY2UoDQogICAgMToobigpIC0gOCkgI3JldGlyYW5kbyBhcyB1bHRpbWFzIDggbGluaGFzDQogICkgJT4lIA0KICByZW5hbWUoDQogICAgZV9jb2xpID0gZXNjaGVyaWNoaWFfY29saSwNCiAgICBkYm8gPSBkZW1hbmRhX2Jpb3F1aW1pY2FfZGVfb3hpZ2VuaW8sDQogICAgbWVyY3VyaW8gPSBtZXJjdXJpb19lbV9taWNyb2dyYW1hX3Bvcl9saXRyb191Z19sDQogICkgJT4lDQogIG11dGF0ZSgNCiAgICBtdW5pY2lwaW8gPSBzdHJfdG9fdGl0bGUobXVuaWNpcGlvKSwNCiAgICBkYXRhX2NvbGV0YSA9IHltZChkYXRhX2NvbGV0YSksDQogICAgYW5vX2NvbGV0YSA9IHllYXIoZGF0YV9jb2xldGEpLA0KICApICU+JQ0KICBkcGx5cjo6c2VsZWN0KCAjcmVvcmRlbmFuZG8gYXMgY29sdW5hcw0KICAgIGMoMToxMCksDQogICAgYW5vX2NvbGV0YSwNCiAgICBldmVyeXRoaW5nKCkNCiAgKQ0KYGBgDQoNCmBgYHtyIEltcG9ydGFuZG8gb3MgZGFkb3N9DQpwbGFuX2xpdG9yYWxfbWVkaW9fYWx0ZXJhciA8LSByZWFkX2V4Y2VsKA0KICAiQzovVXNlcnMvTMOpby9Eb3dubG9hZHMvcGxhbl9saXRvcmFsX21lZGlvLnhscyIsICNhbHRlcmFjYW9fMQ0KICBzaGVldCA9ICJEYWRvc19BanVzdGFkb3MiLCANCiAgY29sX3R5cGVzID0gYygNCiAgICAibnVtZXJpYyIsICJ0ZXh0IiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJ0ZXh0IiwgDQogICAgInRleHQiLCAidGV4dCIsICJ0ZXh0IiwgInRleHQiLCAiZGF0ZSIsIA0KICAgICJkYXRlIiwgInRleHQiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQogICAgIm51bWVyaWMiKSwNCiAgcmFuZ2UgPSAiQTE6QVk5OSIsICNhbHRlcmFjYW9fMg0KICB0cmltX3dzID0gVFJVRQ0KKSAlPiUgDQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgJT4lIA0KICByZW5hbWUoDQogICAgZV9jb2xpID0gZXNjaGVyaWNoaWFfY29saSwNCiAgICBkYm8gPSBkZW1hbmRhX2Jpb3F1aW1pY2FfZGVfb3hpZ2VuaW8sDQogICAgbWVyY3VyaW8gPSBtZXJjdXJpb19lbV9taWNyb2dyYW1hX3Bvcl9saXRyb191Z19sDQogICkgJT4lIA0KICBtdXRhdGUoDQogICAgbXVuaWNpcGlvID0gc3RyX3RvX3RpdGxlKG11bmljaXBpbyksDQogICAgZGF0YV9jb2xldGEgPSB5bWQoZGF0YV9jb2xldGEpLA0KICAgIGFub19jb2xldGEgPSB5ZWFyKGRhdGFfY29sZXRhKSwNCiAgICAjIGhvcmFfY29sZXRhID0gcGFyc2VfZGF0ZXRpbWUoaG9yYV9jb2xldGEpLA0KICApICU+JQ0KICBkcGx5cjo6c2VsZWN0KCAjcmVvcmRlbmFuZG8gYXMgY29sdW5hcw0KICAgIGMoMToxMCksDQogICAgYW5vX2NvbGV0YSwNCiAgICBldmVyeXRoaW5nKCkNCiAgKQ0KYGBgDQoNCiMgU3Vtw6FyaW9zIGVzdGF0w61zdGljb3MgeyNzZWMtc3Vtw6FyaW9zLWVzdGF0w61zdGljb3N9DQoNCmBgYHtyIHN1bWFyaW8sIGVjaG8gPSBUUlVFfQ0Kc3VtYXJpbyA8LSBwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogIGRwbHlyOjpzZWxlY3QoY29kX2VzdGFjYW8sIG94aWdlbmlvX2Rpc3NvbHZpZG8sIGFub19jb2xldGEpICU+JQ0KICBmaWx0ZXIoYW5vX2NvbGV0YSA+ICIyMDEzIiAmDQogICAgICAgICAgIGFub19jb2xldGEgPD0gIjIwMjUiKSAlPiUNCiAgZ3JvdXBfYnkoY29kX2VzdGFjYW8pICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluID0NCiAgICAgIG1pbihveGlnZW5pb19kaXNzb2x2aWRvLA0KICAgICAgICAgIG5hLnJtID0gVFJVRSksDQogICAgcTEgPQ0KICAgICAgcXVhbnRpbGUob3hpZ2VuaW9fZGlzc29sdmlkbywgMC4yMCwNCiAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSksDQogICAgbWVkaWFuID0NCiAgICAgIG1lZGlhbihveGlnZW5pb19kaXNzb2x2aWRvLA0KICAgICAgICAgICAgIG5hLnJtID0gVFJVRSksDQogICAgbWVhbiA9DQogICAgICBtZWFuKG94aWdlbmlvX2Rpc3NvbHZpZG8sDQogICAgICAgICAgIG5hLnJtPSBUUlVFKSwNCiAgICBxMyA9DQogICAgICBxdWFudGlsZShveGlnZW5pb19kaXNzb2x2aWRvLCAwLjgwLA0KICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFKSwNCiAgICBtYXggPQ0KICAgICAgbWF4KG94aWdlbmlvX2Rpc3NvbHZpZG8sDQogICAgICAgICAgbmEucm0gPSBUUlVFKSkNCg0Kc3VtYXJpbw0KYGBgDQoNCiMjIFZpc3VhbGl6YcOnw6NvIGRhIGVzdHJ1dHVyYSBkZSBkYWRvcyBkYSBwbGFuaWxoYSB7I3NlYy12aXN1YWxpemHDp8Ojby1kYS1lc3RydXR1cmEtZGUtZGFkb3MtZGEtcGxhbmlsaGF9DQoNCkNvbmZlcmlyIHNlIG8gdGlwbyBkb3MgZGFkb3MgZXN0w6EgY29ycmV0bywgZGF0YSBlbSBmb3JtYXRvIGRlIGRhdGEgKGRhdGUvZHR0bSksIGPDs2RpZ28gZGEgZXN0YcOnw6NvIGNvbW8gY2hhcmFjdGVyIChjaHIpLCB2YWxvciBtZWRpZG8gZG9zIHBhcsOibWV0cm9zIGNvbW8gZG91YmxlIChkYmwpLg0KDQpgYGB7ciBlc3RydXR1cmEgZGEgcGxhbmlsaGEsfQ0KZ2xpbXBzZShwbGFuX2xpdG9yYWxfbWVkaW8pDQojIHN0cihwbGFuX2xpdG9yYWxfbWVkaW8pICNvdXRyYSBtYW5laXJhIGRlIHZpc3VhbGl6YXIgYSBlU1RSdXR1cmEgDQpgYGANCg0KYGBge3IgVmlzdWFsaXphw6fDo28gZGEgcGxhbmlsaGEgaW1wb3J0YWRhLCBlY2hvID0gRkFMU0V9DQpwYWdlZF90YWJsZShwbGFuX2xpdG9yYWxfbWVkaW8sDQogICAgICAgICAgICBvcHRpb25zID0gbGlzdChyb3dzLnByaW50ID0gMTUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xzLnByaW50ID0gMTApKQ0KYGBgDQoNCiMgUmVxdWlzaXRvcyBwcmEgZ2VyYXIgb3MgZ3LDoWZpY29zIHsjc2VjLXJlcXVpc2l0b3MtcHJhLWdlcmFyLW9zLWdyw6FmaWNvc30NCg0KIyMgRGVmaW5pciBvICp0aGVtZSoNCg0KRGVmaW5pbmRvIHVtYSBjb3IgZGUgbGV0cmEgZSBkZSBmdW5kbyBwYWRyw6NvIGEgc2VyIGFkb3RhZGEgbm9zIGdyw6FmaWNvcy4NCg0KYGBge3Igc2V0dGluZyB0aGVtZX0NCnRoZW1lX2dyYWZzIDwtIGZ1bmN0aW9uKGJnID0gIndoaXRlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICBjb2xvcmFjYW9fbGV0cmEgPSAiYmxhY2siKSB7DQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSANCiAgICAgIGVsZW1lbnRfdGV4dCgNCiAgICAgICAgaGp1c3QgPSAwLjUsDQogICAgICAgIGNvbG9yID0gY29sb3JhY2FvX2xldHJhLA0KICAgICAgICBzaXplID0gMTkpLA0KICAgIA0KICAgIGF4aXMudGl0bGUueCA9IA0KICAgICAgIyBlbGVtZW50X3RleHQoDQogICAgICAjIGNvbG9yID0gY29sb3JhY2FvX2xldHJhLA0KICAgICAgIyBzaXplID0gMTUsDQogICAgICAjIGFuZ2xlID0gMCwpLA0KICAgICAgZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgIGNvbG9yID0gY29sb3JhY2FvX2xldHJhLA0KICAgICAgc2l6ZSA9IDE1LA0KICAgICAgYW5nbGUgPSA5MCksDQogICAgDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoDQogICAgICBjb2xvciA9IGNvbG9yYWNhb19sZXRyYSwNCiAgICAgIHNpemUgPSAxNyksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQogICAgICBjb2xvciA9IGNvbG9yYWNhb19sZXRyYSwNCiAgICAgIHNpemUgPSAxNywNCiAgICAgIGFuZ2xlID0gMCksDQogICAgDQogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gYmcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMC41LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSwNCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNyksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gYmcpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gYmcpLA0KICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKGwgPSA1LCByID0gMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgYiA9IDUsIHQgPSA1KQ0KICApDQp9DQpgYGANCg0KIyMgQ3JpYXIgZnVuw6fDo28gcGFyYSBnZXJhciBib3hwbG90cyBjb20gcGVyY2VudGlzIDIwIGUgODANCg0KYGBge3IgZnVuY2FvIHBlcmNlbnRpbCAyMCBlIDgwfQ0KZiA8LSBmdW5jdGlvbih4KSB7DQogIHIgPC0gcXVhbnRpbGUoeCwgcHJvYnMgPSBjKDAuMTAsIDAuMjAsIDAuNTAsIDAuODAsIDAuOTApKQ0KICBuYW1lcyhyKSA8LSBjKCJ5bWluIiwgImxvd2VyIiwgIm1pZGRsZSIsICJ1cHBlciIsICJ5bWF4IikNCiAgcmV0dXJuKHIpDQp9DQpgYGANCg0KIyBHcsOhZmljb3MgeyNzZWMtZ3LDoWZpY29zIC5ncmFmaWNvc30NCg0KIyMgQWx0ZXJhciBub21lIGUvb3Ugb3JkZW0gZGFzIGVzdGHDp8O1ZXMgeyNzZWMtYWx0ZXJhci1ub21lLWVvdS1vcmRlbS1kYXMtZXN0YcOnw7Vlc30NCg0KPiAqKkF0ZW7Dp8OjbzoqKiBUb21hciBtdWl0byBjdWlkYWRvIGNvbSBhIG9yZGVtIHF1ZSBlc3TDo28gZGlzcG9zdGFzIGFzIGVzdGHDp8O1ZXMuIERldmUtc2Ugc2VtcHJlIHJlc3BlaXRhciBvIHNlbnRpZG8gbmFzY2VudGUgLVw+IGZvei4NCj4NCj4gQ29uZmVyaXIgYSBvcmRlbSBkYXMgZXN0YcOnw7VlcyBhdHJhdsOpcyBkbyBbbWFwYSBpbnRlcmF0aXZvXSgjc2VjLW1hcGEtaW50ZXJhdGl2by1jb20tbG9jYWxpemHDp8Ojby1kb3MtcG9udG9zLWRlLW1vbml0b3JhbWVudG8pLCBRR0lTIG91IEdvb2dsZSBFYXJ0aCBQcm8uDQo+DQo+IEVsYXMgYWNhYmFtIGZpY2FuZG8gZm9yYSBkZSBvcmRlbSBwb3IgY29udGEgZG8gY8OzZGlnbyBkZSBvdHRvYmFjaWFzIFBhcmEgcmVvcmRlbmFyIGFzIGVzdGHDp8O1ZXMsIGF0ZW50ZS1zZSDDoCBmdW7Dp8OjbyBgc2NhbGVfeF9kaXNjcmV0ZWAuDQoNCk5lc3RlIGV4ZW1wbG8gaXJlbW9zIGFwcmVuZGVyIGEgY29tbyBtdWRhciBvIG5vbWUgZGFzIGVzdGHDp8O1ZXMgZSByZW9yZGVuw6EtbGFzLg0KDQpBcyBlc3Rhw6fDtWVzIGVzdMOjbyBuYSBvcmRlbSBjZXJ0YSwgbWFzIHF1ZXJvIGFsdGVyYXIgbyBub21lIGRlbGFzLCBjb21vIGZhw6dvPw0KDQpgYGB7ciBncmFmIG9yZGVtIGNlcnRhLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBmb2xkLnBsb3Q9RkFMU0V9DQoocGxhbl9saXRvcmFsX21lZGlvICU+JQ0KICAgZ2dwbG90KA0KICAgICBhZXMoDQogICAgICAgeCA9IGNvZF9lc3RhY2FvLA0KICAgICAgIHkgPSBveGlnZW5pb19kaXNzb2x2aWRvLA0KICAgICApDQogICApKw0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gLUluZiwgeW1heCA9IDIsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNhYzUwNzkiKSsgIz5waW9yIGNsYXNzZQ0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gMiwgeW1heCA9IDQsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNlYjU2NjEiKSsgI2NsYXNzZSA0DQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSA0LCB5bWF4ID0gNSwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDUsIHltYXggPSA2LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjNzBjMThjIikrICNjbGFzc2UgMg0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluPSA2LCB5bWF4ID0gSW5mLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjOGRjZGViIikrICNjbGFzc2UgMQ0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAnZXJyb3JiYXInLA0KICAgICB3aWR0aCA9IDAuMywNCiAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLA0KICAgKSsNCiAgIHN0YXRfc3VtbWFyeSgNCiAgICAgZnVuLmRhdGEgPSBmLA0KICAgICBnZW9tID0gImJveHBsb3QiLA0KICAgICB3aWR0aCA9IDAuNywNCiAgICAgZmlsbCA9ICcjRjhGOEZGJywNCiAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICBvdXRsaWVyLnNoYXBlID0gMSwgI3NlIGRlaXhhciBOQSBmaWNhIHPDsyBvIGppdHRlciwgc2UgbsOjbywgZGVpeGEgMQ0KICAgKSsNCiAgICMgZmFjZXRfd3JhcCh+cGVyaW9kbykrDQogICBsYWJzKA0KICAgICB0aXRsZSA9ICJPeGlnw6puaW8gRGlzc29sdmlkbyIsDQogICAgIHg9IE5VTEwsDQogICAgIHk9Im1nL0wiDQogICApKw0KICAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbSgNCiAgICAgc2l6ZSA9IDEuMiwNCiAgICAgYWxwaGEgPSAuMjUsDQogICAgIHdpZHRoID0gLjA3LA0KICAgKSsNCiAgIHNjYWxlX3lfY29udGludW91cygNCiAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsMCkpLA0KICAgICBuLmJyZWFrcyA9IDExLA0KICAgICAjIGxpbWl0cyA9IGMoLTAuMywyMSkNCiAgICAgbGltaXRzID0gYygNCiAgICAgICBtaW4ocGxhbl9saXRvcmFsX21lZGlvJG94aWdlbmlvX2Rpc3NvbHZpZG8sIG5hLnJtID0gVFJVRSksDQogICAgICAgbWF4KHBsYW5fbGl0b3JhbF9tZWRpbyRveGlnZW5pb19kaXNzb2x2aWRvLCBuYS5ybSA9IFRSVUUpKzEpDQogICApKw0KICAgIyBzY2FsZV94X2Rpc2NyZXRlKA0KICAgIyAgIGxpbWl0cyA9IGMoDQogICAjICAgICAiODc0MjAxMzAiLA0KICAgIyAgICAgDQogICAjICAgICAiODczMzI1MDAiLA0KICAgIyAgICAgIjg3NDIwMTUwIiwNCiAgICMgICAgICI4NzQyMDM1MCIsDQogICAjICAgICAiODc0MjA1MDAiLA0KICAgIyAgICAgIjg3NTEwMDEwIg0KICAgIyAgICksDQogICAjICAgbGFiZWxzID0gYygNCiAgICMgICAgICJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiINCiAgICMgICApDQogICAjICkrDQogICBnZW9tX3Ntb290aCgNCiAgICAgbWV0aG9kID0gImxtIiwNCiAgICAgc2UgPSBGQUxTRSwgI3NlIGRlaXhhciBUUlVFIGdlcmEgbyBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBkZSA5NSUNCiAgICAgYWVzKGdyb3VwID0gMSksDQogICAgIGFscGhhID0gMC41LA0KICAgICBuYS5ybSA9IFRSVUUsDQogICAgIHNpemUgPSAxDQogICApKw0KICAgdGhlbWVfZ3JhZnMoKQ0KKQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpVdGlsaXphbmRvIG8gYGNvZGUgY2h1bmtgIGFiYWl4byBuw7NzIGFsdGVyYW1vcyBvcyBub21lcyBkYXMgZXN0YcOnw7VlcyBwYXJhIFBNIChvdSBQb250byBkZSBNb25pdG9yYW1lbnRvKSBzZWd1aWRvIGRlIHVtIG7Dum1lcm8uIE8gYFBNMWAgcmVwcmVzZW50YSBvIHBvbnRvIG1haXMgcHLDs3hpbW8gZGFzIG5hc2NlbnRlcywgZW5xdWFudG8gbyBgUE02YCBvIG1haXMgcHLDs3hpbW8gZGEgZm96Lg0KDQpgYGB7ciByZW5vbWVhciBlc3Rhw6fDtWVzIG5vIGdyw6FmaWNvLCBldmFsID0gRkFMU0V9DQpzY2FsZV94X2Rpc2NyZXRlKA0KICBsaW1pdHMgPSBjKA0KICAgICI4NzMzMjUwMCIsDQogICAgIjg3NDIwMTMwIiwNCiAgICANCiAgICAiODc0MjAxNTAiLA0KICAgICI4NzQyMDM1MCIsDQogICAgIjg3NDIwNTAwIiwNCiAgICAiODc1MTAwMTAiDQogICksDQogIGxhYmVscyA9IGMoDQogICAgIlBNMSIsICJQTTIiLCAiUE0zIiwgIlBNNCIsICJQTTUiLCAiUE02Ig0KICApDQopKw0KYGBgDQoNCmBgYHtyIGdyYWYgYWx0ZXJhciBub21lIGVzdCwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZm9sZC5wbG90PUZBTFNFfQ0KKHBsYW5fbGl0b3JhbF9tZWRpbyAlPiUNCiAgIGdncGxvdCgNCiAgICAgYWVzKA0KICAgICAgIHggPSBjb2RfZXN0YWNhbywNCiAgICAgICB5ID0gb3hpZ2VuaW9fZGlzc29sdmlkbywNCiAgICAgKQ0KICAgKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSAyLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjYWM1MDc5IikrICM+cGlvciBjbGFzc2UNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDIsIHltYXggPSA0LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjZWI1NjYxIikrICNjbGFzc2UgNA0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gNCwgeW1heCA9IDUsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNmY2Y3YWIiKSsgI2NsYXNzZSAzDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSA1LCB5bWF4ID0gNiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiIzcwYzE4YyIpKyAjY2xhc3NlIDINCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbj0gNiwgeW1heCA9IEluZiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiIzhkY2RlYiIpKyAjY2xhc3NlIDENCiAgIHN0YXRfc3VtbWFyeSgNCiAgICAgZnVuLmRhdGEgPSBmLA0KICAgICBnZW9tID0gJ2Vycm9yYmFyJywNCiAgICAgd2lkdGggPSAwLjMsDQogICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwNCiAgICkrDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICJib3hwbG90IiwNCiAgICAgd2lkdGggPSAwLjcsDQogICAgIGZpbGwgPSAnI0Y4RjhGRicsDQogICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgb3V0bGllci5zaGFwZSA9IDEsICNzZSBkZWl4YXIgTkEgZmljYSBzw7MgbyBqaXR0ZXIsIHNlIG7Do28sIGRlaXhhIDENCiAgICkrDQogICAjIGZhY2V0X3dyYXAofnBlcmlvZG8pKw0KICAgbGFicygNCiAgICAgdGl0bGUgPSAiT3hpZ8OqbmlvIERpc3NvbHZpZG8iLA0KICAgICB4PSBOVUxMLA0KICAgICB5PSJtZy9MIg0KICAgKSsNCiAgIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oDQogICAgIHNpemUgPSAxLjIsDQogICAgIGFscGhhID0gLjI1LA0KICAgICB3aWR0aCA9IC4wNywNCiAgICkrDQogICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLDApKSwNCiAgICAgbi5icmVha3MgPSAxMSwNCiAgICAgIyBsaW1pdHMgPSBjKC0wLjMsMjEpDQogICAgIGxpbWl0cyA9IGMoDQogICAgICAgbWluKHBsYW5fbGl0b3JhbF9tZWRpbyRveGlnZW5pb19kaXNzb2x2aWRvLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kb3hpZ2VuaW9fZGlzc29sdmlkbywgbmEucm0gPSBUUlVFKSsxKQ0KICAgKSsNCiAgIHNjYWxlX3hfZGlzY3JldGUoDQogICAgIGxpbWl0cyA9IGMoDQogICAgICAgIjg3MzMyNTAwIiwNCiAgICAgICAiODc0MjAxMzAiLA0KICAgICAgICI4NzQyMDE1MCIsDQogICAgICAgIjg3NDIwMzUwIiwNCiAgICAgICAiODc0MjA1MDAiLA0KICAgICAgICI4NzUxMDAxMCINCiAgICAgKSwNCiAgICAgbGFiZWxzID0gYygNCiAgICAgICAiUE0xIiwgIlBNMiIsICJQTTMiLCAiUE00IiwgIlBNNSIsICJQTTYiDQogICAgICkNCiAgICkrDQogICBnZW9tX3Ntb290aCgNCiAgICAgbWV0aG9kID0gImxtIiwNCiAgICAgc2UgPSBGQUxTRSwgI3NlIGRlaXhhciBUUlVFIGdlcmEgbyBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBkZSA5NSUNCiAgICAgYWVzKGdyb3VwID0gMSksDQogICAgIGFscGhhID0gMC41LA0KICAgICBuYS5ybSA9IFRSVUUsDQogICAgIHNpemUgPSAxDQogICApKw0KICAgdGhlbWVfZ3JhZnMoKQ0KKQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpQZXJjZWJhIHF1ZSBpcmVtb3MgdHJvY2FyIGEgb3JkZW0gZGFzIGVzdGHDp8O1ZXMuIEFudGVzIGEgZXN0YcOnw6NvIGA4NzMzMjUwMGAgZXJhIGEgcHJpbWVpcmEgYSBzZXIgbGlzdGFkYSBkZW50cm8gZGEgZnVuw6fDo28gYGxpbWl0cyA9IGMoKWAsIGVsYSBlcmEsIHBvcnRhbnRvLCBvIGBQTTFgLiBBZ29yYSBvIGBQTTFgIHNlcsOhIGEgYDg3NDIwMTMwYC4gQ29tcGFyZSBvIGPDs2RpZ28gZSBvIGdyw6FmaWNvIGFiYWl4byBjb20gbyBhbnRlcmlvci4NCg0KYGBge3IgcmVvcmRlbmFyIGVzdGHDp8O1ZXMgbm8gZ3LDoWZpY28sIGV2YWwgPSBGQUxTRX0NCnNjYWxlX3hfZGlzY3JldGUoDQogIGxpbWl0cyA9IGMoDQogICAgIjg3NDIwMTMwIiwNCiAgICAiODczMzI1MDAiLA0KICAgIA0KICAgICI4NzQyMDE1MCIsDQogICAgIjg3NDIwMzUwIiwNCiAgICAiODc0MjA1MDAiLA0KICAgICI4NzUxMDAxMCINCiAgKSwNCiAgbGFiZWxzID0gYygNCiAgICAiUE0xIiwgIlBNMiIsICJQTTMiLCAiUE00IiwgIlBNNSIsICJQTTYiDQogICkNCikrDQpgYGANCg0KYGBge3IgZ3JhZiBhbHRlcmFyIG9yZGVtIGRhcyBlc3QsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZvbGQucGxvdD1GQUxTRX0NCihwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogICBnZ3Bsb3QoDQogICAgIGFlcygNCiAgICAgICB4ID0gY29kX2VzdGFjYW8sDQogICAgICAgeSA9IG94aWdlbmlvX2Rpc3NvbHZpZG8sDQogICAgICkNCiAgICkrDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gMiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2FjNTA3OSIpKyAjPnBpb3IgY2xhc3NlDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAyLCB5bWF4ID0gNCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ViNTY2MSIpKyAjY2xhc3NlIDQNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDQsIHltYXggPSA1LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjZmNmN2FiIikrICNjbGFzc2UgMw0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gNSwgeW1heCA9IDYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM3MGMxOGMiKSsgI2NsYXNzZSAyDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW49IDYsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnMoDQogICAgIHRpdGxlID0gIk94aWfDqm5pbyBEaXNzb2x2aWRvIiwNCiAgICAgeD0gTlVMTCwNCiAgICAgeT0ibWcvTCINCiAgICkrDQogICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICBzaXplID0gMS4yLA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwwKSksDQogICAgIG4uYnJlYWtzID0gMTEsDQogICAgICMgbGltaXRzID0gYygtMC4zLDIxKQ0KICAgICBsaW1pdHMgPSBjKA0KICAgICAgIG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kb3hpZ2VuaW9fZGlzc29sdmlkbywgbmEucm0gPSBUUlVFKSwNCiAgICAgICBtYXgocGxhbl9saXRvcmFsX21lZGlvJG94aWdlbmlvX2Rpc3NvbHZpZG8sIG5hLnJtID0gVFJVRSkrMSkNCiAgICkrDQogICBzY2FsZV94X2Rpc2NyZXRlKA0KICBsaW1pdHMgPSBjKA0KICAgICI4NzQyMDEzMCIsDQogICAgDQogICAgIjg3MzMyNTAwIiwNCiAgICAiODc0MjAxNTAiLA0KICAgICI4NzQyMDM1MCIsDQogICAgIjg3NDIwNTAwIiwNCiAgICAiODc1MTAwMTAiDQogICksDQogIGxhYmVscyA9IGMoDQogICAgIlBNMSIsICJQTTIiLCAiUE0zIiwgIlBNNCIsICJQTTUiLCAiUE02Ig0KICApDQopKw0KICAgZ2VvbV9zbW9vdGgoDQogICAgIG1ldGhvZCA9ICJsbSIsDQogICAgIHNlID0gRkFMU0UsICNzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQogICAgIGFlcyhncm91cCA9IDEpLA0KICAgICBhbHBoYSA9IDAuNSwNCiAgICAgbmEucm0gPSBUUlVFLA0KICAgICBzaXplID0gMQ0KICAgKSsNCiAgIHRoZW1lX2dyYWZzKCkNCikNCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIk9rIG1hcy4uLiBlIHNlIGV1IG7Do28gcXVpc2VyIGFsdGVyYXIgbyBjw7NkaWdvIG90dG9iYWNpYXMgcGFyYSBgUE0xYCwgYFBNMmAsIHPDsyBhIG9yZGVtIGRhcyBlc3Rhw6fDtWVzLCBvIHF1ZSBkZXZvIGZhemVyPyIgQmFzdGEgcmVwbGljYXIgYSBzZXF1w6puY2lhICpjb3JyZXRhKiBkYXMgZXN0YcOnw7VlcyBkZSBgbGltaXRzID0gYygpYCBkZW50cm8gZGEgZnVuw6fDo28gYGxhYmVscyA9IGMoKWAuDQoNCmBgYHtyIHJlb3JkZW5hciBlc3Rhw6fDtWVzIG5vIGdyw6FmaWNvIHNlbSBhbHRlcmFyIG5vbWUsIGV2YWwgPSBGQUxTRX0NCiAgIHNjYWxlX3hfZGlzY3JldGUoDQogICAgIGxpbWl0cyA9IGMoDQogICAgICAgIjg3NDIwMTMwIiwNCiAgICAgICAiODczMzI1MDAiLA0KICAgICAgICI4NzQyMDE1MCIsDQogICAgICAgIjg3NDIwMzUwIiwNCiAgICAgICAiODc0MjA1MDAiLA0KICAgICAgICI4NzUxMDAxMCINCiAgICAgKSwNCiAgICAgbGFiZWxzID0gYygNCiAgICAgICAiODc0MjAxMzAiLA0KICAgICAgICI4NzMzMjUwMCIsDQogICAgICAgIjg3NDIwMTUwIiwNCiAgICAgICAiODc0MjAzNTAiLA0KICAgICAgICI4NzQyMDUwMCIsDQogICAgICAgIjg3NTEwMDEwIg0KICAgICApDQogICApKw0KYGBgDQoNCmBgYHtyIGdyYWYgYWx0ZXJhciBvcmRlbSBkYXMgZXN0IHNlbSBhbHRlcmFyIG5vbWUsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZvbGQucGxvdD1GQUxTRX0NCihwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogICBnZ3Bsb3QoDQogICAgIGFlcygNCiAgICAgICB4ID0gY29kX2VzdGFjYW8sDQogICAgICAgeSA9IG94aWdlbmlvX2Rpc3NvbHZpZG8sDQogICAgICkNCiAgICkrDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gMiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2FjNTA3OSIpKyAjPnBpb3IgY2xhc3NlDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAyLCB5bWF4ID0gNCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ViNTY2MSIpKyAjY2xhc3NlIDQNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDQsIHltYXggPSA1LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjZmNmN2FiIikrICNjbGFzc2UgMw0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gNSwgeW1heCA9IDYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM3MGMxOGMiKSsgI2NsYXNzZSAyDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW49IDYsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnMoDQogICAgIHRpdGxlID0gIk94aWfDqm5pbyBEaXNzb2x2aWRvIiwNCiAgICAgeD0gTlVMTCwNCiAgICAgeT0ibWcvTCINCiAgICkrDQogICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICBzaXplID0gMS4yLA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwwKSksDQogICAgIG4uYnJlYWtzID0gMTEsDQogICAgICMgbGltaXRzID0gYygtMC4zLDIxKQ0KICAgICBsaW1pdHMgPSBjKA0KICAgICAgIG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kb3hpZ2VuaW9fZGlzc29sdmlkbywgbmEucm0gPSBUUlVFKSwNCiAgICAgICBtYXgocGxhbl9saXRvcmFsX21lZGlvJG94aWdlbmlvX2Rpc3NvbHZpZG8sIG5hLnJtID0gVFJVRSkrMSkNCiAgICkrDQogICBzY2FsZV94X2Rpc2NyZXRlKA0KICAgICBsaW1pdHMgPSBjKA0KICAgICAgICI4NzQyMDEzMCIsDQogICAgICAgIjg3MzMyNTAwIiwNCiAgICAgICAiODc0MjAxNTAiLA0KICAgICAgICI4NzQyMDM1MCIsDQogICAgICAgIjg3NDIwNTAwIiwNCiAgICAgICAiODc1MTAwMTAiDQogICAgICksDQogICAgIGxhYmVscyA9IGMoDQogICAgICAgIjg3NDIwMTMwIiwNCiAgICAgICAiODczMzI1MDAiLA0KICAgICAgICI4NzQyMDE1MCIsDQogICAgICAgIjg3NDIwMzUwIiwNCiAgICAgICAiODc0MjA1MDAiLA0KICAgICAgICI4NzUxMDAxMCINCiAgICAgKQ0KICAgKSsNCiAgIGdlb21fc21vb3RoKA0KICAgICBtZXRob2QgPSAibG0iLA0KICAgICBzZSA9IEZBTFNFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAgICBhZXMoZ3JvdXAgPSAxKSwNCiAgICAgYWxwaGEgPSAwLjUsDQogICAgIG5hLnJtID0gVFJVRSwNCiAgICAgc2l6ZSA9IDENCiAgICkrDQogICB0aGVtZV9ncmFmcygpDQopDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCk9iczogUGFyYSBhIEJhY2lhIEhpZHJvZ3LDoWZpY2EgZG8gUmlvIEdyYXZhdGHDrSBlc3NlIHByb2Nlc3NvIMOpIG5lY2Vzc8OhcmlvLg0KDQo+IFNlbXByZSB0b21hciBjdWlkYWRvIGNvbSBvcyBsaW1pdGVzIGRvICoqZWl4byB5KiouIERlaXhlaSBjb21vIHBhZHLDo28gbyBSIGJ1c2NhciBhdXRvbWF0aWNhbWVudGUgcXVhbCBvIHZhbG9yIG3DrW5pbW8gZSBtw6F4aW1vIGRhcXVlbGUgcGFyw6JtZXRybywgbWFzIG8gaWRlYWwgw6kgcXVlIHNlIGFqdXN0ZSBjYXNvIGEgY2Fzby4NCg0KQ2FzbyBxdWVpcmEgYWx0ZXJhciBvIHRhbWFuaG8gZG9zIG91dGxpZXJzLCBhbHRlcmFyIG8gYHNpemVgIG5lc3NlIHRyZWNobyBkb3MgY8OzZGlnb3M6DQoNCmBgYHtyIGFsdGVyYXIgdGFtYW5obyBkbyBvdXRsaWVyLCBldmFsID0gRkFMU0V9DQpnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICAjIGdyb3Vwb25YID0gRkFMU0UsDQogICAgIHNpemUgPSAxLjIsIA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KYGBgDQoNCj4gVG9kb3Mgb3MgZ3LDoWZpY29zIGZvcmFtIGdlcmFkb3MgdXRpbGl6YW5kbyBjb21vIHBhZHLDo28gb3MgbGltaXRlcyBkYSBSZXNvbHXDp8OjbyBuwrogMzU3LzA1IGRvIENPTkFNQSBwYXJhIGFtYmllbnRlcyAqKmzDs3RpY29zKiouIENhc28gcXVlaXJhIGFsdGVyYXIgb3MgbGltaXRlcyBwYXJhIGFkZXF1YXIgYW9zIGFtYmllbnRlcyAqKmzDqm50aWNvcyoqLCBkZXZlLXNlIGVkaXRhciBvcyBgeW1pbmAgZSBgeW1heGAgZGUgY2FkYSByZXTDom5ndWxvIChgcmVjdGApIGRvIHJlZmVyaWRvIHBhcsOibWV0cm8uDQo+DQo+IE7Do28gZXNxdWVjZXIgcXVlIG8gUiBlbnRlbmRlIGEgY2FzYSBkZWNpbWFsIGNvbW8gcG9udG8sIGUgbsOjbyBjb21vIHbDrXJndWxhLg0KDQpgYGB7ciBhbWJpZW50ZSBsw7N0aWNvIHggbMOqbnRpY28sIGV2YWwgPSBGQUxTRX0NCmFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgeW1pbiA9IDEzLjMsIHltYXggPSBJbmYsDQogICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICBmaWxsID0gIiNhYzUwNzkiKSsgIz5waW9yIGNsYXNzZQ0KYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICB5bWluID0gMy43LCB5bWF4ID0gMTMuMywNCiAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCmFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgeW1pbiA9IDAsIHltYXggPSAzLjcsDQogICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQpgYGANCg0KIyMgUGFyw6JtZXRyb3MgZGUgUXVhbGlkYWRlIGRhIMOBZ3VhIHsjc2VjLXBhcsOibWV0cm9zLWRlLXF1YWxpZGFkZS1kYS3DoWd1YX0NCg0KIyMjIE94aWfDqm5pbyBEaXNzb2x2aWRvIHsjc2VjLW94aWfDqm5pby1kaXNzb2x2aWRvfQ0KDQpgYGB7ciBHcsOhZmljbyBPRCwgZmlnLmNhcD0iT3hpZ8OqbmlvIERpc3NvbHZpZG8iLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmb2xkLnBsb3Q9RkFMU0V9DQooZ3JhZl9vZCA8LSBwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogICBnZ3Bsb3QoDQogICAgIGFlcygNCiAgICAgICB4ID0gY29kX2VzdGFjYW8sDQogICAgICAgeSA9IG94aWdlbmlvX2Rpc3NvbHZpZG8sDQogICAgICkNCiAgICkrDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gMiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2FjNTA3OSIpKyAjPnBpb3IgY2xhc3NlDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAyLCB5bWF4ID0gNCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ViNTY2MSIpKyAjY2xhc3NlIDQNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDQsIHltYXggPSA1LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjZmNmN2FiIikrICNjbGFzc2UgMw0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gNSwgeW1heCA9IDYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM3MGMxOGMiKSsgI2NsYXNzZSAyDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW49IDYsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnMoDQogICAgIHRpdGxlID0gIk94aWfDqm5pbyBEaXNzb2x2aWRvIiwNCiAgICAgeD0gTlVMTCwNCiAgICAgeT0ibWcvTCINCiAgICkrDQogICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICBzaXplID0gMS4yLA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwwKSksDQogICAgIG4uYnJlYWtzID0gMTEsDQogICAgICMgbGltaXRzID0gYygtMC4zLDIxKQ0KICAgICBsaW1pdHMgPSBjKA0KICAgICAgIG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kb3hpZ2VuaW9fZGlzc29sdmlkbywgbmEucm0gPSBUUlVFKSwNCiAgICAgICBtYXgocGxhbl9saXRvcmFsX21lZGlvJG94aWdlbmlvX2Rpc3NvbHZpZG8sIG5hLnJtID0gVFJVRSkrMSkNCiAgICkrDQogICAjIHNjYWxlX3hfZGlzY3JldGUoDQogICAjICAgbGltaXRzID0gYygNCiAgICMgICAgICI4NzMzMjUwMCIsDQogICAjICAgICAiODc0MjAxMzAiLA0KICAgIyAgICAgIjg3NDIwMTUwIiwNCiAgICMgICAgICI4NzQyMDM1MCIsDQogICAjICAgICAiODc0MjA1MDAiLA0KICAgIyAgICAgIjg3NTEwMDEwIg0KICAgIyAgICksDQogICAjICAgbGFiZWxzID0gYygNCiAgICMgICAgICJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiINCiAgICMgICApDQogICAjICkrDQogICBnZW9tX3Ntb290aCgNCiAgICAgbWV0aG9kID0gImxtIiwNCiAgICAgc2UgPSBGQUxTRSwgI3NlIGRlaXhhciBUUlVFIGdlcmEgbyBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBkZSA5NSUNCiAgICAgYWVzKGdyb3VwID0gMSksDQogICAgIGFscGhhID0gMC41LA0KICAgICBuYS5ybSA9IFRSVUUsDQogICAgIHNpemUgPSAxDQogICApKw0KICAgdGhlbWVfZ3JhZnMoKQ0KKQ0KYGBgDQoNCiMjIyBEQk8geyNzZWMtZGJvfQ0KDQpgYGB7ciBHcsOhZmljbyBEQk8sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBmaWcuY2FwPSJEZW1hbmRhIEJpb3F1w61taWNhIGRlIE94aWfDqm5pbyIsIGZvbGQucGxvdD1GQUxTRX0NCihncmFmX2RibyA8LSBnZ3Bsb3QocGxhbl9saXRvcmFsX21lZGlvLA0KICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IGNvZF9lc3RhY2FvLA0KICAgICAgICAgICAgICAgICAgIHkgPSBkYm8pKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDEwLCB5bWF4ID0gSW5mLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjYWM1MDc5IikrICM+cGlvciBjbGFzc2UNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDUsIHltYXggPSAxMCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDMsIHltYXggPSA1LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjNzBjMThjIikrICNjbGFzc2UgMg0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gMCwgeW1heCA9IDMsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnModGl0bGUgPSAiRGVtYW5kYSBCaW9xdcOtbWljYSBkZSBPeGlnw6puaW8iLA0KICAgICAgICB4PSJFc3Rhw6fDo28iLA0KICAgICAgICB5PSJtZy9MIikrDQogICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICAjIGdyb3Vwb25YID0gRkFMU0UsDQogICAgIHNpemUgPSAxLjIsDQogICAgIGFscGhhID0gLjI1LA0KICAgICB3aWR0aCA9IC4wNywNCiAgICkrDQogICAjIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiODczOTg1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk4MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5NTAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNTUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA2OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDk5MDAiKSwNCiAgICMgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiIsICJQTTciKQ0KICAgIyApKw0KICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjAzLDAuMDMpKSwNCiAgICAgICAgICAgICAgICAgICAgICBuLmJyZWFrcyA9IDgsDQogICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygNCiAgICAgICAgICAgICAgICAgICAgICAgIG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kZGJvLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgMTANCiAgICAgICAgICAgICAgICAgICAgICAgICMgbWF4KHBsYW5fbGl0b3JhbF9tZWRpbyRkYm8sIG5hLnJtID0gVFJVRSkNCiAgICAgICAgICAgICAgICAgICAgICAgICksDQogICAgICAgICAgICAgICAgICAgICAgdHJhbnMgPSAibG9nMTAiKSsNCiAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsDQogICAgICAgICAgICAgICBzZT1GQUxTRSwgI3NlIGRlaXhhciBUUlVFIGdlcmEgbyBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBkZSA5NSUNCiAgICAgICAgICAgICAgIGFlcyhncm91cD0xKSwNCiAgICAgICAgICAgICAgIGFscGhhPS41LA0KICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEpKw0KICAgdGhlbWVfZ3JhZnMoKQ0KKQ0KYGBgDQoNCiMjIyAqRXNjaGVyaWNoaWEgY29saSoNCg0KYGBge3IgR3LDoWZpY28gRWNvbGksIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBmaWcuY2FwPSJFc2NoZXJpY2hpYS1jb2xpIiwgZm9sZC5wbG90PUZBTFNFfQ0KKGdyYWZfZWNvbGkgPC0gcGxhbl9saXRvcmFsX21lZGlvICU+JSANCiAgIGdncGxvdChhZXMoY29kX2VzdGFjYW8sDQogICAgICAgICAgICAgIGVfY29saSkpKw0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gMzIwMCwgeW1heCA9IEluZiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2FjNTA3OSIpKyAjPnBpb3IgY2xhc3NlDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSA4MDAsIHltYXggPSAzMjAwLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjZmNmN2FiIikrICNjbGFzc2UgMw0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gMTYwLCB5bWF4ID0gODAwLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjNzBjMThjIikrICNjbGFzc2UgMg0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gMCwgeW1heCA9IDE2MCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiIzhkY2RlYiIpKyAjY2xhc3NlIDENCiAgIHN0YXRfc3VtbWFyeSgNCiAgICAgZnVuLmRhdGEgPSBmLA0KICAgICBnZW9tID0gJ2Vycm9yYmFyJywNCiAgICAgd2lkdGggPSAwLjMsDQogICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwNCiAgICkrDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICJib3hwbG90IiwNCiAgICAgd2lkdGggPSAwLjcsDQogICAgIGZpbGwgPSAnI0Y4RjhGRicsDQogICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgb3V0bGllci5zaGFwZSA9IDEsICNzZSBkZWl4YXIgTkEgZmljYSBzw7MgbyBqaXR0ZXIsIHNlIG7Do28sIGRlaXhhIDENCiAgICkrDQogICAjIGZhY2V0X3dyYXAofnBlcmlvZG8pKw0KICAgbGFicyh0aXRsZSA9ICIqRXNjaGVyaWNoaWEgY29saSoiLA0KICAgICAgICB4PSJFc3Rhw6fDo28iLA0KICAgICAgICB5PSJOTVAvMTAwbUwiKSsNCiAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wMSwgMC4wMSkpLA0KICAgICAgICAgICAgICAgICAgICAgICMgbi5icmVha3MgPSA5LA0KICAgICAgICAgICAgICAgICAgICAgIG4uYnJlYWtzID0gNiwNCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kZV9jb2xpLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KHBsYW5fbGl0b3JhbF9tZWRpbyRlX2NvbGksIG5hLnJtID0gVFJVRSkpLA0KICAgICAgICAgICAgICAgICAgICAgIHRyYW5zID0gImxvZzEwIiwNCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6Om51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpbWFsLm1hcmsgPSAiLCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpZy5tYXJrID0gIiAiKSkrDQogICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICBzaXplID0gMS4yLA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KICMgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKCI4NzM5ODUwMCIsDQogIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTgwIiwNCiAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5MDAiLA0KICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk1MCIsDQogIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA1NTAwIiwNCiAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDY5MDAiLA0KICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwOTkwMCIpLA0KICMgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiIsICJQTTciKQ0KICMgKSsNCiBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLA0KIHNlPUZBTFNFLCAjc3RhcmRhbmQgZXJyb3IgPSBkZXN2aW8gcGFkcsOjbyAtPiBzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQogICAgICAgICAgICAgYWVzKGdyb3VwPTEpLA0KICAgICAgICAgICAgIGFscGhhPSAwLjUsICN0cmFuc3BhcmVuY2lhIGRlIDUwJQ0KICAgICAgICAgICAgIG5hLnJtID0gVFJVRSwgI3JlbW92ZXIgTkFzDQogICAgICAgICAgICAgc2l6ZSA9IDEpKw0KIHRoZW1lX2dyYWZzKCkrDQogICB0aGVtZSgNCiAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQogICAgICAgYW5nbGUgPSA5MCwNCiAgICAgICAjIHNpemU9MTUsDQogICAgICAgIyBmYWNlPTINCiAgICAgKSwNCiAgICAgcGxvdC50aXRsZSA9IA0KICAgICAgIGVsZW1lbnRfbWFya2Rvd24oDQogICAgICAgICBoanVzdCA9IDAuNSwNCiAgICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgIHNpemUgPSAxOSksDQogICApDQopDQpgYGANCg0KIyMjIEbDs3Nmb3JvIFRvdGFsIHsjc2VjLWbDs3Nmb3JvLXRvdGFsfQ0KDQpgYGB7ciBHcsOhZmljbyBmw7NzZm9ybyB0b3RhbCwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZpZy5jYXA9IkbDs3Nmb3JvIHRvdGFsIiwgZm9sZC5wbG90PUZBTFNFfQ0KKGdyYWZfcHRvdCA8LSBnZ3Bsb3QocGxhbl9saXRvcmFsX21lZGlvLA0KICAgICAgICAgICAgICAgICAgICAgYWVzKGNvZF9lc3RhY2FvLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGZvc2Zvcm9fdG90YWwpKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDAuMTUsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNhYzUwNzkiKSsgIz5waW9yIGNsYXNzZQ0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gMC4xLCB5bWF4ID0gMC4xNSwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDAsIHltYXggPSAwLjEsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnModGl0bGUgPSAiRsOzc2Zvcm8gdG90YWwiLA0KICAgICAgICB4PSJFc3Rhw6fDo28iLA0KICAgICAgICB5PSJtZy9MIikrDQogICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAuMDMsMC4wMykpLA0KICAgICAgICAgICAgICAgICAgICAgIG4uYnJlYWtzID0gOCwNCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kZm9zZm9yb190b3RhbCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kZm9zZm9yb190b3RhbCksIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgdHJhbnMgPSAibG9nMTAiLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IC4wMDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2ltYWwubWFyayA9ICIsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlnLm1hcmsgPSAiICIpDQogICApKw0KICAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbSgNCiAgICAgc2l6ZSA9IDEuMiwNCiAgICAgYWxwaGEgPSAuMjUsDQogICAgIHdpZHRoID0gLjA3LA0KICAgKSsNCiAgICMgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKCI4NzM5ODUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTgwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk1MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA1NTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDY5MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwOTkwMCIpLA0KICAgIyAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlBNMSIsICJQTTIiLCAiUE0zIiwgIlBNNCIsICJQTTUiLCAiUE02IiwgIlBNNyIpDQogICAjICkrDQogICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLA0KICAgICAgICAgICAgICAgc2U9RkFMU0UsICNzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQogICAgICAgICAgICAgICBhZXMoZ3JvdXA9MSksDQogICAgICAgICAgICAgICBhbHBoYT0uNSwNCiAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSwNCiAgICAgICAgICAgICAgIHNpemUgPSAxKSsNCiAgIHRoZW1lX2dyYWZzKCkNCikNCmBgYA0KDQojIyMgTml0cm9nw6puaW8gYW1vbmlhY2FsIHsjc2VjLW5pdHJvZ8OqbmlvLWFtb25pYWNhbH0NCg0KYGBge3IgR3LDoWZpY28gTml0cm9nw6puaW8gQW1vbmlhY2FsLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZmlnLmNhcD0iTml0cm9nw6puaW8gQW1vbmlhY2FsIiwgZm9sZC5wbG90PUZBTFNFfQ0KKGdyYWZfbmFtb24gPC0gZ2dwbG90KHBsYW5fbGl0b3JhbF9tZWRpbywNCiAgICAgICAgICAgICAgICAgYWVzKGNvZF9lc3RhY2FvLA0KICAgICAgICAgICAgICAgICAgICAgbml0cm9nZW5pb19hbW9uaWFjYWwpKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDEzLjMsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNhYzUwNzkiKSsgIz5waW9yIGNsYXNzZQ0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gMy43LCB5bWF4ID0gMTMuMywNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDAsIHltYXggPSAzLjcsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnModGl0bGUgPSAiTml0cm9nw6puaW8gYW1vbmlhY2FsIiwNCiAgICAgICAgeD0iRXN0YcOnw6NvIiwNCiAgICAgICAgeT0ibWcvTCIpKw0KICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjAxLCAwLjA1KSksDQogICAgICAgICAgICAgICAgICAgICAgbi5icmVha3MgPSA5LA0KICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMobWluKHBsYW5fbGl0b3JhbF9tZWRpbyRuaXRyb2dlbmlvX2Ftb25pYWNhbCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDE1DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kbml0cm9nZW5pb19hbW9uaWFjYWwsIG5hLnJtID0gVFJVRSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksDQogICAgICAgICAgICAgICAgICAgICAgdHJhbnMgPSAibG9nMTAiLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IC4wMDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2ltYWwubWFyayA9ICIsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlnLm1hcmsgPSAiICIpKSsNCiAgIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oDQogICAgIHNpemUgPSAxLjIsDQogICAgIGFscGhhID0gLjI1LA0KICAgICB3aWR0aCA9IC4wNywNCiAgICkrDQogICAjIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiODczOTg1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk4MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5NTAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNTUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA2OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDk5MDAiKSwNCiAgICMgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiIsICJQTTciKQ0KICAgIyApKw0KICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwNCiAgICAgICAgICAgICAgIHNlPUZBTFNFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAgICAgICAgICAgICAgYWVzKGdyb3VwPTEpLA0KICAgICAgICAgICAgICAgYWxwaGE9LjUsDQogICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUsDQogICAgICAgICAgICAgICBzaXplID0gMSkrDQogICB0aGVtZV9ncmFmcygpDQopDQpgYGANCg0KIyMjIFR1cmJpZGV6IHsjc2VjLXR1cmJpZGV6fQ0KDQpgYGB7ciBHcsOhZmljbyBUdXJiaWRleiwgZmlnLmNhcD0idHVyYmlkZXoiLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZm9sZC5wbG90PUZBTFNFfQ0KKGdyYWZfdHVyYiA8LSBnZ3Bsb3QocGxhbl9saXRvcmFsX21lZGlvLA0KICAgICAgICAgICAgICAgICAgIGFlcyhjb2RfZXN0YWNhbywNCiAgICAgICAgICAgICAgICAgICAgICAgdHVyYmlkZXopKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDEwMCwgeW1heCA9IEluZiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2FjNTA3OSIpKyAjPnBpb3IgY2xhc3NlDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSA0MCwgeW1heCA9IDEwMCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDAsIHltYXggPSA0MCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiIzhkY2RlYiIpKyAjY2xhc3NlIDENCiAgIHN0YXRfc3VtbWFyeSgNCiAgICAgZnVuLmRhdGEgPSBmLA0KICAgICBnZW9tID0gJ2Vycm9yYmFyJywNCiAgICAgd2lkdGggPSAwLjMsDQogICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSwNCiAgICkrDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICJib3hwbG90IiwNCiAgICAgd2lkdGggPSAwLjcsDQogICAgIGZpbGwgPSAnI0Y4RjhGRicsDQogICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgb3V0bGllci5zaGFwZSA9IDEsICNzZSBkZWl4YXIgTkEgZmljYSBzw7MgbyBqaXR0ZXIsIHNlIG7Do28sIGRlaXhhIDENCiAgICkrDQogICAjIGZhY2V0X3dyYXAofnBlcmlvZG8pKw0KICAgbGFicyh0aXRsZSA9ICJUdXJiaWRleiIsDQogICAgICAgIHg9IkVzdGHDp8OjbyIsDQogICAgICAgIHk9IlVOVCIpKw0KICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjA1LCAwLjA1KSksDQogICAgICAgICAgICAgICAgICAgICAgbi5icmVha3MgPSA4LA0KICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoDQogICAgICAgICAgICAgICAgICAgICAgICAjIDEsDQogICAgICAgICAgICAgICAgICAgICAgICBtaW4ocGxhbl9saXRvcmFsX21lZGlvJHR1cmJpZGV6LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIyA1MDANCiAgICAgICAgICAgICAgICAgICAgICAgIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kdHVyYmlkZXosIG5hLnJtID0gVFJVRSkNCiAgICAgICAgICAgICAgICAgICAgICApLA0KICAgICAgICAgICAgICAgICAgICAgIHRyYW5zID0gImxvZzEwIiwNCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6Om51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpbWFsLm1hcmsgPSAiLCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpZy5tYXJrID0gIiAiKSkrDQogICAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbSgNCiAgICAgc2l6ZSA9IDEuMiwNCiAgICAgYWxwaGEgPSAuMjUsDQogICAgIHdpZHRoID0gLjA3LA0KICAgKSsNCiAgICMgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKCI4NzM5ODUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTgwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk1MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA1NTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDY5MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwOTkwMCIpLA0KICAgIyAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlBNMSIsICJQTTIiLCAiUE0zIiwgIlBNNCIsICJQTTUiLCAiUE02IiwgIlBNNyIpDQogICAjICkrDQogICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLA0KICAgICAgICAgICAgICAgc2U9RkFMU0UsICNzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQogICAgICAgICAgICAgICBhZXMoZ3JvdXA9MSksDQogICAgICAgICAgICAgICBhbHBoYT0uNSwNCiAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSwNCiAgICAgICAgICAgICAgIHNpemUgPSAxKSsNCiAgIHRoZW1lX2dyYWZzKCkNCikNCmBgYA0KDQojIyMgcEggeyNzZWMtcEh9DQoNCmBgYHtyIEdyw6FmaWNvIHBILCBmaWcuY2FwPSJwSCIsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBmb2xkLnBsb3Q9RkFMU0V9DQooZ3JhZl9wSCA8LSBnZ3Bsb3QocGxhbl9saXRvcmFsX21lZGlvLA0KICAgICAgICAgICAgICAgICBhZXMoY29kX2VzdGFjYW8sDQogICAgICAgICAgICAgICAgICAgICBwaCkpKw0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbj0tSW5mLA0KICAgICAgICAgICAgeG1heD1JbmYsDQogICAgICAgICAgICB5bWluPS1JbmYsDQogICAgICAgICAgICB5bWF4PTYsDQogICAgICAgICAgICBhbHBoYT0xLA0KICAgICAgICAgICAgZmlsbD0iI2ViNTY2MSIpKyAjY2xhc3NlIDQNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW49LUluZiwNCiAgICAgICAgICAgIHhtYXg9SW5mLA0KICAgICAgICAgICAgeW1pbj05LA0KICAgICAgICAgICAgeW1heD1JbmYsDQogICAgICAgICAgICBhbHBoYT0xLA0KICAgICAgICAgICAgZmlsbD0iI2ViNTY2MSIpKyAjY2xhc3NlIDQNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW49LUluZiwNCiAgICAgICAgICAgIHhtYXg9SW5mLA0KICAgICAgICAgICAgeW1pbj02LA0KICAgICAgICAgICAgeW1heD05LA0KICAgICAgICAgICAgYWxwaGE9MSwNCiAgICAgICAgICAgIGZpbGw9IiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnModGl0bGUgPSAicEgiLA0KICAgICAgICB4PSJFc3Rhw6fDo28iLA0KICAgICAgICB5PSIiKSsNCiAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wMSwgMC4wMSkpLA0KICAgICAgICAgICAgICAgICAgICAgIG4uYnJlYWtzID0gOCwNCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDQsMTEpLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2ltYWwubWFyayA9ICIsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlnLm1hcmsgPSAiICIpDQogICAgICAgICAgICAgICAgICAgICAgKSsNCiAgICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICBzaXplID0gMS4yLA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KICAgIyBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoIjg3Mzk4NTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5ODAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODkwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTUwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDU1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNjkwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA5OTAwIiksDQogICAjICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiUE0xIiwgIlBNMiIsICJQTTMiLCAiUE00IiwgIlBNNSIsICJQTTYiLCAiUE03IikNCiAgICMgKSsNCiAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsDQogICAgICAgICAgICAgICBzZT1GQUxTRSwgI3NlIGRlaXhhciBUUlVFIGdlcmEgbyBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBkZSA5NSUNCiAgICAgICAgICAgICAgIGFlcyhncm91cD0xKSwNCiAgICAgICAgICAgICAgIGFscGhhPS41LA0KICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEpKw0KICAgdGhlbWVfZ3JhZnMoKQ0KKQ0KYGBgDQoNCiMjIyBTw7NsaWRvcyBUb3RhaXMgeyNzZWMtc8OzbGlkb3MtdG90YWlzfQ0KDQpPIHBhcsOibWV0cm8gYFPDs2xpZG9zIFRvdGFpc2AgbsOjbyB0ZXZlIG1lZGnDp8O1ZXMgbm8gcGVyw61vZG8gYW5hbGlzYWRvLCBlbnTDo28gZmljYSBhcm1hemVuYWRvIG5hIHRhYmVsYSBjb21vIHZhbG9yIHZhemlvLCBvdSBgcmBOQVxgLg0KDQpgYGB7ciBHcsOhZmljbyBTw7NsVG90LCBmaWcuY2FwPSJzw7NsaWRvcy10b3RhaXMiLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZm9sZC5wbG90PUZBTFNFLCBlcnJvciA9IFRSVUV9DQojIChncmFmX3NvbGlkb3NfdG90YWlzIDwtIGdncGxvdChwbGFuX2xpdG9yYWxfbWVkaW8sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoY29kX2VzdGFjYW8sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc29saWRvc190b3RhaXMpKSsNCiMgICAgYW5ub3RhdGUoInJlY3QiLA0KIyAgICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiMgICAgICAgICAgICAgeW1pbiA9IDUwMCwgeW1heCA9IEluZiwNCiMgICAgICAgICAgICAgYWxwaGEgPSAxLA0KIyAgICAgICAgICAgICBmaWxsPSIjYWM1MDc5IikrICM+cGlvciBjbGFzc2UNCiMgICAgYW5ub3RhdGUoInJlY3QiLA0KIyAgICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiMgICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSA1MDAsDQojICAgICAgICAgICAgIGFscGhhID0gMSwNCiMgICAgICAgICAgICAgZmlsbD0iIzhkY2RlYiIpKyAjY2xhc3NlIDENCiMgc3RhdF9zdW1tYXJ5KA0KIyAgICAgIGZ1bi5kYXRhID0gZiwNCiMgICAgICBnZW9tID0gJ2Vycm9yYmFyJywNCiMgICAgICB3aWR0aCA9IDAuMywNCiMgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQojICAgICkrDQojICAgIHN0YXRfc3VtbWFyeSgNCiMgICAgICBmdW4uZGF0YSA9IGYsDQojICAgICAgZ2VvbSA9ICJib3hwbG90IiwNCiMgICAgICB3aWR0aCA9IDAuNywNCiMgICAgICBmaWxsID0gJyNGOEY4RkYnLA0KIyAgICAgIGNvbG9yID0gImJsYWNrIiwNCiMgICAgICBvdXRsaWVyLnNoYXBlID0gMSwgI3NlIGRlaXhhciBOQSBmaWNhIHPDsyBvIGppdHRlciwgc2UgbsOjbywgZGVpeGEgMQ0KIyAgICApKw0KIyAgICAjIGZhY2V0X3dyYXAofnBlcmlvZG8pKw0KIyAgICBsYWJzKHRpdGxlID0gIlPDs2xpZG9zIHRvdGFpcyIsDQojICAgICAgICAgeD0iRXN0YcOnw6NvIiwNCiMgICAgICAgICB5PSIiKSsNCiMgICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjAxLCAwLjA1KSksDQojICAgICAgICAgICAgICAgICAgICAgICBuLmJyZWFrcyA9IDgsDQojICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kc29saWRvc190b3RhaXMsIG5hLnJtID0gVFJVRSkNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwNCiMgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDEsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaW1hbC5tYXJrID0gIiwiLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpZy5tYXJrID0gIiAiKSkrDQojICAgIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oDQojICAgICAgc2l6ZSA9IDEuMiwNCiMgICAgICBhbHBoYSA9IC4yNSwNCiMgICAgICB3aWR0aCA9IC4wNywNCiMgICAgKSsNCiMgICAgIyBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoIjg3Mzk4NTAwIiwgDQojICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk4MCIsIA0KIyAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5MDAiLCANCiMgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTUwIiwgDQojICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNTUwMCIsIA0KIyAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDY5MDAiLCANCiMgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA5OTAwIiksDQojICAgICMgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiIsICJQTTciKQ0KIyAgICAjICkrDQojICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsDQojICAgICAgICAgICAgICAgIHNlPUZBTFNFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KIyAgICAgICAgICAgICAgICBhZXMoZ3JvdXA9MSksDQojICAgICAgICAgICAgICAgIGFscGhhPS41LA0KIyAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUsDQojICAgICAgICAgICAgICAgIHNpemUgPSAxKSsNCiMgICAgdGhlbWVfZ3JhZnMoKQ0KIyApDQpgYGANCg0KIyMjIENvbmR1dGl2aWRhZGUgeyNzZWMtY29uZHV0aXZpZGFkZX0NCg0KYGBge3IgR3LDoWZpY28gY29uZF9lbGV0LCBmaWcuY2FwPSJjb25kdXRpdmlkYWRlLWVsZXRyaWNhIiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZvbGQucGxvdD1GQUxTRX0NCihncmFmX2NvbmRfZWxldCA8LSBnZ3Bsb3QocGxhbl9saXRvcmFsX21lZGlvLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoY29kX2VzdGFjYW8sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25kdXRpdmlkYWRlKSkrDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSA1MDAsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNlYjU2NjEiKSsgI2NsYXNzZSA0DQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAwLCB5bWF4ID0gNTAwLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjOGRjZGViIikrICNjbGFzc2UgMQ0KICBzdGF0X3N1bW1hcnkoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9zdW1tYXJ5KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnModGl0bGUgPSAiQ29uZHV0aXZpZGFkZSBlbMOpdHJpY2EiLA0KICAgICAgICB4PSJFc3Rhw6fDo28iLA0KICAgICAgICB5PSLCtW1ob3MvY20iKSsNCiAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wNSwgMC4wNSkpLA0KICAgICAgICAgICAgICAgICAgICAgIG4uYnJlYWtzID0gOCwNCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kY29uZHV0aXZpZGFkZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kY29uZHV0aXZpZGFkZSwgbmEucm0gPSBUUlVFKSksDQogICAgICAgICAgICAgICAgICAgICAgdHJhbnMgPSAibG9nMTAiLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2ltYWwubWFyayA9ICIsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlnLm1hcmsgPSAiICIpKSsNCiAgIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oDQogICAgIHNpemUgPSAxLjIsDQogICAgIGFscGhhID0gLjI1LA0KICAgICB3aWR0aCA9IC4wNywNCiAgICkrDQogICAjIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiODczOTg1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk4MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5NTAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNTUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA2OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDk5MDAiKSwNCiAgICMgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiIsICJQTTciKQ0KICAgIyApKw0KICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwNCiAgICAgICAgICAgICAgIHNlPUZBTFNFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAgICAgICAgICAgICAgYWVzKGdyb3VwPTEpLA0KICAgICAgICAgICAgICAgYWxwaGE9LjUsDQogICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUsDQogICAgICAgICAgICAgICBzaXplID0gMSkrDQogICB0aGVtZV9ncmFmcygpKw0KICAgdGhlbWUoDQogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KA0KICAgICAgIGFuZ2xlID0gOTAsDQogICAgICAgIyBzaXplPTE1LA0KICAgICAgICMgZmFjZT0yDQogICAgICkNCiAgICkNCikNCmBgYA0KDQojIyBBbsOhbGlzZSBhbyBsb25nbyBkbyB0ZW1wbyB7I3NlYy1hbsOhbGlzZS1hby1sb25nby1kby10ZW1wb30NCg0KUGFyYSBnZXJhciB1bSBncsOhZmljbyBhbyBsb25nbyBkbyB0ZW1wbyBwcmEgY2FkYSB1bWEgZGFzIGVzdGHDp8O1ZXMgw6kgbmVjZXNzw6FyaW8gYWx0ZXJhciBvIGBhbm9faW5pY2lhbGAgZSBvIGBhbm9fZmluYWxgLiBUYW1iw6ltIMOpIG5lY2Vzc8OhcmlvIHNlbGVjaW9uYXIgcXVhbCBwYXLDom1ldHJvIHF1ZSBzZSBxdWVyIGZhemVyIGEgdmlzdWFsaXphw6fDo28uDQoNCmBgYHtyIGdyw6FmaWNvIGFvIGxvbmdvIGRvIHRlbXBvLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZm9sZC5wbG90PUZBTFNFfQ0KYW5vX2luaWNpYWwgPC0gMjAxNQ0KYW5vX2ZpbmFsIDwtIDIwMjINCg0KKHRpbWVsaW5lIDwtIHBsYW5fbGl0b3JhbF9tZWRpbyAlPiUNCiAgZmlsdGVyKGFub19jb2xldGEgPiBhbm9faW5pY2lhbCAmDQogICAgICAgICAgIGFub19jb2xldGEgPD0gYW5vX2ZpbmFsKSAlPiUNCiAgZHBseXI6OnNlbGVjdChjb2RfZXN0YWNhbywgZV9jb2xpLCBkYXRhX2NvbGV0YSkgJT4lDQogIGdyb3VwX2J5KGNvZF9lc3RhY2FvKSAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcyh4ID0gZGF0YV9jb2xldGEsDQogICAgICAgIHkgPSBlX2NvbGksDQogICAgICAgIGNvbG9yID0gY29kX2VzdGFjYW8NCiAgICApKSsNCiAgICBnZW9tX2xpbmUoDQogICAgICAjIGFlcyhjb2xvciA9IENPRElHTyksDQogICAgICBuYS5ybSA9IFRSVUUpKw0KICAgIGdlb21fcG9pbnQoDQogICAgICAjIGFlcyhjb2xvciA9IENPRElHTyksDQogICAgICBuYS5ybSA9IFRSVUUpKw0KICAgIHNjYWxlX3hfZGF0ZSgNCiAgICAgIGxpbWl0cyA9IGFzLkRhdGUoYygNCiAgICAgICAgeW1kKGdsdWUoInthbm9faW5pY2lhbH0tMDEtMDEiKSksDQogICAgICAgIHltZChnbHVlKCJ7YW5vX2ZpbmFsfS0wMS0wMSIpKQ0KICAgICAgICAjIE5BICNwb2RlIHVzYXIgTkEgdGFtYsOpbQ0KICAgICAgKSksDQogICAgICBleHBhbmQgPSBjKDAuMCwgMC4wKSwNCiAgICAgIGRhdGVfYnJlYWtzID0gIjIgeWVhcnMiLA0KICAgICAgbWlub3JfYnJlYWtzID0gIjEgeWVhcnMiLA0KICAgICAgZGF0ZV9sYWJlbHMgPSAiJVkiLA0KICAgICkrDQogICMgZ2VvbV9zbW9vdGgoDQogICMgICBtZXRob2QgPSAibG0iLCAjcmVncmVzc2FvIGxpbmVhcg0KICAjICAgc2UgPSBUUlVFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAjICAgYWVzKGdyb3VwID0gMSksDQogICMgICBhbHBoYSA9LjUsDQogICMgICBuYS5ybSA9IFRSVUUsDQogICMgICBzaXplID0gMC4zLA0KICAjICAgIyBmdWxscmFuZ2UgPSBUUlVFLA0KICAjICAgc2hvdy5sZWdlbmQgPSBUUlVFDQogICMgKSsNCiAgc3RhdF9zbW9vdGgoDQogICAgZ2VvbSA9ICJzbW9vdGgiLA0KICAgICMgc3BhbiA9IDAuMiwNCiAgICBzZSA9IFRSVUUsICNzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQogICAgIyBhZXMoZ3JvdXAgPSAxKSwNCiAgICAjIGFscGhhID0uNSwNCiAgICBuYS5ybSA9IFRSVUUsDQogICAgIyBzaXplID0gMC4zLA0KICAgIGZ1bGxyYW5nZSA9IFRSVUUsDQogICAgc2hvdy5sZWdlbmQgPSBUUlVFDQogICkrDQogIGZhY2V0X3dyYXAoDQogICAgfmNvZF9lc3RhY2FvLA0KICAgIG5yb3cgPSA0LA0KICApKw0KICB0aGVtZV9idygpDQopDQpgYGANCg0KIyMgQ29ycmVsYcOnw6NvIHsjc2VjLWNvcnJlbGHDp8Ojb30NCg0KYGBge3IgQ29ycmVsYcOnw6NvLCBmaWcuY2FwPSJjb3JyZWxhw6fDo28tcGFyYW1ldHJvcy1xdWFsaWRhZGUtYWd1YSIsIHRpbWVfaXQgPSBUUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZvbGQucGxvdD1GQUxTRX0NCnBhcmFtZXRyb3NfaXFhX2xpdF9tZWRpbyA8LSBwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogIGRwbHlyOjpzZWxlY3QoY29kX2VzdGFjYW8sDQogICAgICAgICBwaCwNCiAgICAgICAgIGRibywNCiAgICAgICAgIGVfY29saSwNCiAgICAgICAgIG5pdHJvZ2VuaW9fYW1vbmlhY2FsLA0KICAgICAgICAgIyBuaXRyb19ramVsZGFobCwNCiAgICAgICAgICMgbml0cm9fdG90YWwsDQogICAgICAgICBmb3Nmb3JvX3RvdGFsLA0KICAgICAgICAgdGVtcGVyYXR1cmFfZGFfYWd1YSwNCiAgICAgICAgIHR1cmJpZGV6LA0KICAgICAgICAgc29saWRvc190b3RhaXMsDQogICAgICAgICBveGlnZW5pb19kaXNzb2x2aWRvLA0KICAgICAgICAgY29uZHV0aXZpZGFkZSwNCiAgICAgICAgIGFub19jb2xldGENCiAgICAgICAgICkgDQoNCnBhcmFtZXRyb3NfaXFhX2xpdF9tZWRpbyAlPiUgDQogIGRwbHlyOjpzZWxlY3QoDQogICAgLWNvZF9lc3RhY2FvLA0KICAgIC1hbm9fY29sZXRhLA0KICAgIC1zb2xpZG9zX3RvdGFpcw0KICAgICkgJT4lDQogICMgZ3JvdXBfYnkoY29kX2VzdGFjYW8pICU+JQ0KICByZW5hbWUoDQogICAgQ0UgPSBjb25kdXRpdmlkYWRlLA0KICAgIE9EID0gb3hpZ2VuaW9fZGlzc29sdmlkbywNCiAgICAjIFNUID0gc29saWRvc190b3RhaXMsDQogICAgVHVyYiA9IHR1cmJpZGV6LA0KICAgIFRlbXAgPSB0ZW1wZXJhdHVyYV9kYV9hZ3VhLA0KICAgIFB0b3QgPSBmb3Nmb3JvX3RvdGFsLA0KICAgIE5BbW9uID0gbml0cm9nZW5pb19hbW9uaWFjYWwsDQogICAgcEggPSBwaCwNCiAgICBEQk8gPSBkYm8sDQogICAgRV9jb2xpID0gZV9jb2xpDQogICAgIyBOVEsgPSBuaXRyb19ramVsZGFobA0KICApICU+JSANCiAgZ2djb3JyKA0KICAgIG1ldGhvZCA9DQogICAgImNvbXBsZXRlLm9icyIsDQogICAgIyAicGVhcnNvbiIsDQogICAgIyAicGFpcndpc2UiLA0KICAgIG5hbWUgPSAiQ29ycmVsYcOnw6NvIiwNCiAgICBsYWJlbCA9IFRSVUUsDQogICAgbGFiZWxfYWxwaGEgPSBUUlVFLA0KICAgIGRpZ2l0cyA9IDMsDQogICAgbG93ID0gIiMzQjlBQjIiLA0KICAgIG1pZCA9ICIjRUVFRUVFIiwNCiAgICBoaWdoID0gIiNGMjFBMDAiLA0KICAgICMgcGFsZXR0ZSA9ICJSZFlsQnUiLA0KICAgIGxheW91dC5leHAgPSAwLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJsZWZ0IiwNCiAgICBsYWJlbF9yb3VuZCA9IDMsDQogICAgIyBsZWdlbmQuc2l6ZSA9IDE4LA0KICAgIGdlb20gPSAidGlsZSIsDQogICAgbmJyZWFrcyA9IDEwLA0KICApKw0KICBsYWJzKHRpdGxlID0gIkNvcnJlbGHDp8OjbyBlbnRyZSBwYXLDom1ldHJvcyBmw61zaWNvLXF1w61taWNvcyBuYVxuQmFjaWEgSGlkcm9ncsOhZmljYSBkbyBMaXRvcmFsIE3DqWRpbyIpKw0KICB0aGVtZV9saW5lZHJhdygpKw0KICB0aGVtZSgNCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuMTUsIDAuNiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAjIGxlZ2VuZC5zcGFjaW5nID0gdW5pdChlbGVtZW50X3RleHQoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1bml0cyA9IDUpDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxNikNCiAgKQ0KYGBgDQoNCiMjIyBDb3JyZWxhw6fDo28gZW50cmUgcGFyw6JtZXRyb3MgcXVlIGNvbXDDtWVtIG8gSVFBIGNvbSBzaWduaWZpY8OibmNpYSBlc3RhdMOtc3RpY2ENCg0KYGBge3IgZ3JhZi1jb3JyZWwtZXN0YXRpc3RpY2EsIHRpbWVfaXQgPSBUUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0V9DQojIEdyw6FmaWNvIGRhcyBjb3JyZWxhw6fDtWVzIGVudHJlIHRvZG9zIG9zIHBhcsOibWV0cm9zIGNvbSBzaWduaWZpY8OibmNpYQ0KY29ycmVsX0lRQV9saXRfbWVkaW8gPC0gcGFyYW1ldHJvc19pcWFfbGl0X21lZGlvICU+JQ0KICBkcGx5cjo6c2VsZWN0KC1jb2RfZXN0YWNhbykgJT4lDQogIGdncGFpcnModGl0bGUgPSAiQ29ycmVsYcOnw6NvIGVudHJlIHBhcsOibWV0cm9zIHF1ZSBjb21ww7VlbSBvIElRQSIsDQogICAgICAgICAgYXhpc0xhYmVscyA9ICJzaG93IikNCiMgY29ycmVsX0lRQV9saXRfbWVkaW8NCmBgYA0KDQojIyBTYWx2YXIgb3MgZ3LDoWZpY29zIHsjc2VjLXNhbHZhci1vcy1ncsOhZmljb3N9DQoNClJlcGxpY2FyIGVzc2UgbW9kZWxvIHByb3MgZ3LDoWZpY29zIHF1ZSBkZXNlamEgc2FsdmFyLlwNCjEuIENyaWFyIG5vdm8gY29kZSBjaHVuayAoYEN0cmwrQWx0K0lgKVwNCjIuIENvcGlhciBhIGbDs3JtdWxhIGFiYWl4b1wNCjMuIENvbGFyIG5lc3NlIG5vdm8gY29kZSBjaHVua1wNCjQuDQoNCk9zIGdyw6FmaWNvcyBmaWNhcsOjbyBzYWx2b3MgZW0gdW1hIHBhc3RhIHF1ZSBpcsOhIHNlciBjcmlhZGEgYSBwYXJ0aXIgZG8gY8OzZGlnby4NCg0KYGBge3Igc2FsdmFyLWdyYWZpY29zLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCmdnc2F2ZSgiZ3JhZl9vZC5wbmciLA0KICAgICAgIHBsb3QgPSBncmFmX29kLCAjYWx0ZXJhY2FvDQogICAgICAgcGF0aCA9ICIuL2dyYWZpY29zIiwNCiAgICAgICBkcGkgPSAzMDAsDQogICAgICAgdHlwZSA9ICJjYWlybyIpDQpgYGANCg0KIyBNYXBhcyB7I3NlYy1tYXBhc30NCg0KIyMgUGFjb3RlcyBwcmEgZ2VyYcOnw6NvIGRlIG1hcGFzIHsjc2VjLXBhY290ZXMtcHJhLWdlcmHDp8Ojby1kZS1tYXBhcyAucGFjb3Rlc30NCg0KYGBge3IgcGFjb3Rlcy1nZW9lc3BhY2lhaXMsIG1lc3NhZ2UgPSBUUlVFLCB3YXJuaW5nID0gRkFMU0V9DQpwYWNtYW46OnBfbG9hZChyYXN0ZXIsIGxlYWZsZXQsIHNmDQogICAgICAgICAgICAgICAjIHByZXR0eW1hcHIsIHJqc29uLCByb3NtLA0KICAgICAgICAgICAgICAgIyBnZ3NwYXRpYWwNCiAgICAgICAgICAgICAgICMgcmdkYWwsIHJnZW9zLA0KICAgICAgICAgICAgICAgIyBndG9vbHMsIHRpZHl2ZXJzZSwgcm5hdHVyYWxlYXJ0aCwNCiAgICAgICAgICAgICAgICMgcm5hdHVyYWxlYXJ0aGRhdGEsIHJldGljdWxhdGUsIG1hcHRvb2xzLA0KICAgICAgICAgICAgICAgIyBtYXBzLCBnZ3Bsb3QyLCBnZ3NwYXRpYWwsIHJnZW9zLCBnZ21hcA0KICAgICAgICAgICAgICAgKQ0KYGBgDQoNCiMjIE1hcGEgZXN0w6F0aWNvIHsjc2VjLW1hcGEtZXN0w6F0aWNvfQ0KDQpJbXBvcnRhbmRvIGFzIGluZm9ybWHDp8O1ZXMgbmVjZXNzw6FyaWFzIHByYSBnZXJhciBtYXBhcyBkZSBwcmVjaXBpdGHDp8Ojby5cDQpGb250ZTogR0FETSBbXjFdLCBbXjJdDQoNClteMV06IDxodHRwczovL2dhZG0ub3JnL21hcHMvQlJBLmh0bWw+DQoNClteMl06IDxodHRwczovL2dhZG0ub3JnL2RhdGEuaHRtbD4NCg0KYGBge3IgbWFwYS1lc3RhdGljbywgZmlnLmNhcCA9ICJNYXBhIGVzdMOhdGljbyBkbyBSUyJ9DQpCcmFzaWwgPC0gZ2V0RGF0YSgNCiAgJ0dBRE0nLA0KICBjb3VudHJ5ID0gJ0JyYXppbCcsDQogIGxldmVsID0gMw0KKSAlPiUNCiAgc3RfYXNfc2YoKQ0KDQpSUyA8LSBzdWJzZXQoQnJhc2lsLA0KICAgICAgICAgICAgIE5BTUVfMSA9PSAiUmlvIEdyYW5kZSBkbyBTdWwiKQ0KDQpsYmwgPC0gZGF0YS5mcmFtZShtb250aF9hYmIgPSBtb250aC5hYmIsDQogICAgICAgICAgICAgICAgICBtZXMgPSAxOjEyKQ0KDQpwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogIGdncGxvdCgNCiAgICAjIGFlcyh4ID0gbG9uZ3RpdHVkZSwNCiAgICAjICAgICB5ID0gbGF0aXR1ZGUsDQogICAgIyAgICAgbWFwX2lkID0gcmVnaW9uKQ0KICApKw0KICBnZW9tX3NmKA0KICAgIGRhdGEgPSBSUw0KICApKw0KICB0aGVtZV9idygpDQoNCiMgRGVmaW5pbmRvIG8gU1JDDQpSUyA8LSBSUyAlPiUNCiAgc3RfdHJhbnNmb3JtIChjcnMgPSA0Njc0KSAjNDMyNiA9IFdHUzg0LCA0Njc0ID0gU0lSR0FTMjAwMA0KYGBgDQoNCiMjIE1hcGEgaW50ZXJhdGl2byBjb20gbG9jYWxpemHDp8OjbyBkb3MgcG9udG9zIGRlIG1vbml0b3JhbWVudG8geyNzZWMtbWFwYS1pbnRlcmF0aXZvLWNvbS1sb2NhbGl6YcOnw6NvLWRvcy1wb250b3MtZGUtbW9uaXRvcmFtZW50b30NCg0KYGBge3IgbWFwYS1pbnRlcmF0aXZvLCBmaWcuY2FwID0gIk1hcGEgaW50ZXJhdGl2byJ9DQpsZWFmbGV0KFJTKSAlPiUgDQogIGFkZFByb3ZpZGVyVGlsZXMoDQogICAgIkVzcmkuV29ybGRJbWFnZXJ5IiAjSW1hZ2VtIGRlIHNhdMOpbGl0ZQ0KICAgICMgIk9wZW5TdHJlZXRNYXAuTWFwbmlrIiAjT3BlblN0cmVldE1hcCAtPiBTb2Z0d2FyZSBsaXZyZQ0KICApICU+JSANCiAgYWRkQ2lyY2xlTWFya2VycygNCiAgICBkYXRhID0gcGxhbl9saXRvcmFsX21lZGlvLA0KICAgIGxuZyA9IH5sb25naXR1ZGUsDQogICAgbGF0ID0gfmxhdGl0dWRlLA0KICAgIHBvcHVwID0gfnBhc3RlKA0KICAgICAgIjxiPkVzdGHDp8Ojbzo8L2I+Iix7Y29kX2VzdGFjYW99LCI8YnI+IiwNCiAgICAgICI8Yj5SZWN1cnNvIGjDrWRyaWNvOjwvYj4iLCByZWN1cnNvX2hpZHJpY28sICI8YnI+IiwNCiAgICAgICI8Yj5NdW5pY8OtcGlvOjwvYj4iLCBtdW5pY2lwaW8sDQogICAgICBzZXAgPSAiICINCiAgICApDQogICkgDQpgYGANCg0KIyMgTWFwYSBkZSBwcmVjaXBpdGHDp8OjbyBhbnVhbA0KDQpgYGB7ciBFeHRyYWluZG8gb3MgZGFkb3MgcmFzdGVyIGRlIHByZWNpcGl0YcOnw6NvLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCiMgc3RfY2VudHJvaWQoUlMpDQojIA0KIyBQcmVjIDwtIGdldERhdGEoDQojICAgIndvcmxkY2xpbSIsIA0KIyAgIHZhciA9ICJwcmVjIiwgDQojICAgcmVzID0gMC41LCANCiMgICBsYXQgPSBjKC0zMC4wMzMwNTYsIC0yOS42ODQxNyksICNwcm9jdXJhciBsYXQgbG9uZyBubyBnb29nbGUgZSBhbHRlcmFyIGFxdWkNCiMgICBsb24gPSBjKC01MS4yMzAwMDAsIC01My44MDY5NCkNCiMgKQ0KIyANCiMgUHJlY19SUyA8LSBQcmVjICU+JSANCiMgICBjcm9wKFJTKSAlPiUgDQojICAgbWFzayhSUywgbmEucm0gPSBUUlVFKQ0KIyANCiMgcGxvdChQcmVjX1JTKQ0KIyANCiMgUFBBbnVhbF9SUyA8LSBkby5jYWxsKCJzdW0iLCANCiMgICAgICAgICAgICAgICAgICAgICAgICB1bnN0YWNrKFByZWNfUlMpKQ0KIyBwbG90KFBQQW51YWxfUlMpDQpgYGANCg0KYGBge3IgRWxhYm9yYW5kbyBvcyBtZXNlcyBkZSBwcmVjaXBpdGHDp8OjbywgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQojIHZscyA8LSByYXN0ZXJUb1BvaW50cyhQcmVjX1JTKSAlPiUgDQojICAgYXNfdGliYmxlKCkgJT4lIA0KIyAgIGdhdGhlcih2YXIsIHZhbHVlLCAteCwgLXkpICU+JSANCiMgICBtdXRhdGUobWVzID0gcGFyc2VfbnVtYmVyKHZhcikpICU+JSANCiMgICBpbm5lcl9qb2luKC4sIGxibCwgYnkgPSAnbWVzJykgJT4lIA0KIyAgIGRwbHlyOjpzZWxlY3QoeCwgeSwgbW9udGhfYWJiLCB2YWx1ZSkgJT4lIA0KIyAgIG11dGF0ZShtb250aF9hYmIgPSBmYWN0b3IobW9udGhfYWJiLCBsZXZlbHMgPSBtb250aC5hYmIpKQ0KIyANCiMgdmxzICU+JSANCiMgICBmaWx0ZXIobW9udGhfYWJiID09ICdKYW4nKQ0KIyANCiMgc3VtbWFyeSh2bHMkdmFsdWUpICNkZXNjb2JyZSBvIHZhbG9yIG3DrW5pbW8sIG3DqWRpbyBlIG3DoXhpbW8gZGUgcHJlY2lwaXRhw6fDo28NCmBgYA0KDQojIyBNYXBhIGNvbSBwcmVjaXBpdGHDp8OjbyBtZW5zYWwNCg0KQ2FzbyBxdWVpcmEgZ2VyYXIgdW0gbWFwYSBjb20gYSBwcmVjaXBpdGHDp8OjbyBtZW5zYWwsIGFsdGVybmFyIG8gaW5jbHVkZSBwYXJhIGBUUlVFYC4gQSBnZXJhw6fDo28gZGVzc2UgbWFwYSBkZW1hbmRhIGJhc3RhbnRlIHByb2Nlc3NhbWVudG8sIHJlY29tZW5kw6F2ZWwgbWFudGVyIGBpbmNsdWRlID0gRkFMU0VgIGUgYGVjaG8gPSBGQUxTRWAuDQoNCmBgYHtyIG1hcGFzLXByZWNpcGl0YWNhby1tZW5zYWwsIGluY2x1ZGUgPSBUUlVFLCBlY2hvID0gRkFMU0V9DQojIGNvcmVzMTwtIGMoJyNmZjQyMjMnLCcjZjE5ZTIxJywnI2ZmZWUyMScsJyMwMGZmZmYnLCAnIzEwYWViZScsICcjMTY1ZGZmJywnIzkzMzFkYycpDQojIGNvcmVzMjwtIGMoJyM5MzMxZGMnLCAnIzE2NWRmZicsICcjMTBhZWJlJywgJyMwMGZmZmYnLCAnI2ZmZWUyMScsICcjZjE5ZTIxJywgJyNmZjQyMjMnKQ0KIyANCiMgDQojIChnZyA8LSBnZ3Bsb3QodmxzKSAgKw0KIyAgICAgZ2VvbV90aWxlKGFlcyh4ID0geCwgDQojICAgICAgICAgICAgICAgICAgIHkgPSB5LCANCiMgICAgICAgICAgICAgICAgICAgZmlsbCA9IHZhbHVlKSkgKw0KIyAgICAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3VycyA9IGNvcmVzMSwgDQojICAgICAgICAgICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICd3aGl0ZScsIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLCAyNTApLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAyNTAsIDI1KSkgKw0KIyAgICAgZ2VvbV9zZihkYXRhID0gUlMsIA0KIyAgICAgICAgICAgICBmaWxsID0gTkEsIA0KIyAgICAgICAgICAgICBjb2xvciA9ICdibGFjaycsIA0KIyAgICAgICAgICAgICBzaXplID0gMC4yKSsNCiMgICAgIGZhY2V0X3dyYXAofiBtb250aF9hYmIpICsNCiMgICAgICMgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoLTcyLjUsIC03MS4wLCAtNjkuNSkpICsNCiMgICAgIGdndGl0bGUoIlByZWNpcGl0YcOnw6NvIG1lbnNhbCAtIFJTIikrDQojICAgICBsYWJzKHRpdGxlID0gJ1ByZWNpcGl0YcOnw6NvIE1lbnNhbCAtIFJTJywNCiMgICAgICAgICAgZmlsbCA9ICdtbScsICANCiMgICAgICAgICAgeCA9ICdMb25naXR1ZGUnLCANCiMgICAgICAgICAgeSA9ICdMYXRpdHVkZScsIA0KIyAgICAgICAgICBjYXB0aW9uID0gIkxlb25hcmRvIEZlcm5hbmRlcyBXaW5rIikgKw0KIyAgICAgbGFicygNCiMgICAgICAgY2FwdGlvbiA9ICJGb250ZTogaHR0cHM6Ly9vc21kYXRhLm9wZW5zdHJlZXRtYXAuZGUvIg0KIyAgICAgKSsNCiMgICAgIHRoZW1lX2J3KCkgKw0KIyAgICAgdGhlbWUoDQojICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksDQojICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQojICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQojICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChzaXplID0gMiwgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiKSwNCiMgICAgICAgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoNSwgJ2xpbmUnKSwNCiMgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScsDQojICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoDQojICAgICAgICAgc2l6ZSA9IDE2LCANCiMgICAgICAgICBoanVzdCA9IDAuNSwgDQojICAgICAgICAgY29sb3IgPSAiYmxhY2siLCANCiMgICAgICAgICBmYWNlID0gImJvbGQiDQojICAgICAgICksDQojICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KA0KIyAgICAgICAgIGZhY2UgPSAiYm9sZCIsIA0KIyAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgDQojICAgICAgICAgc2l6ZSA9IDgNCiMgICAgICAgKSwNCiMgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQojICAgICAgICAgYW5nbGUgPSA5MCwNCiMgICAgICAgICBmYWNlID0gImJvbGQiLCANCiMgICAgICAgICBjb2xvciA9ICJibGFjayIsIA0KIyAgICAgICAgIHNpemUgPSA4DQojICAgICAgICksDQojICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoDQojICAgICAgICAgZmFjZT0gJ2JvbGQnLCANCiMgICAgICAgICBzaXplPSAxNCwgDQojICAgICAgICAgaGp1c3Q9IDAuNSwgDQojICAgICAgICAgY29sb3I9ICdibGFjaycNCiMgICAgICAgKSwNCiMgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSd3aGl0ZScpLA0KIyAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KA0KIyAgICAgICAgIHNpemUgPSAxMSwgDQojICAgICAgICAgaGp1c3QgPSAwLjgsIA0KIyAgICAgICAgIGZhY2UgPSAiaXRhbGljIiwgDQojICAgICAgICAgY29sb3IgPSAicmVkIiwgIyIjNGU0ZDQ3Ig0KIyAgICAgICAgIGZhbWlseT0ic2VyaWYiDQojICAgICAgICksDQojICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dCgNCiMgICAgICAgICBzaXplID0gMTAsIA0KIyAgICAgICAgIGhqdXN0ID0gMC45NSwgDQojICAgICAgICAgY29sb3IgPSAiYmxhY2siLA0KIyAgICAgICApDQojICAgICApICsNCiMgICAgIGd1aWRlcyhzaGFwZSA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAxMCkpKQ0KIyApDQoNCnBhY21hbjo6cF9sb2FkKA0KICBEaWFncmFtbWVSDQopDQpgYGANCg0KIyBSZWZlcsOqbmNpYXMgLSBMaW5rcyDDunRlaXMgeyNzZWMtbGlua3Mtw7p0ZWlzfQ0KDQpSZWNvbWVuZG8sIGFiYWl4bywgYWxndW1hcyByZWZlcsOqbmNpYXMuIFRhbWLDqW0gZGVpeG8gdW1hIHRyaWxoYSBkZSBhcHJlbmRpemFkbyBxdWUganVsZ28gc2VyIG1haXMgZsOhY2lsIGRvIHF1ZSBhIHF1ZSBwZXJjb3JyaSwgY29uZm9ybWUgZGlhZ3JhbWEgYWJhaXhvLg0KDQpgYGB7cn0NCkRpYWdyYW1tZVI6OmdyVml6KCJkaWdyYXBoIHsNCiAgZ3JhcGggWw0KICBsYXlvdXQgPSBkb3QsIA0KICByYW5rZGlyID0gTFINCiAgXQ0KICANCiAgbm9kZSBbc2hhcGUgPSBvdmFsXSAjcmVjdGFuZ2xlDQogIHJlYzEgW2xhYmVsID0gJ1RlbnRhciByZXByb2R1emlyIGPDs2RpZ29zXG5kZSBvdXRyYXMgcGVzc29hcyddDQogIHJlYzIgW2xhYmVsID0gJ0VudGVuZGVyIGEgZ3JhbcOhdGljYVxuZG9zIGdyw6FmaWNvcyddDQogIHJlYzMgW2xhYmVsID0gICdTdGVwIDMuID8/PyddDQogIHJlYzQgW2xhYmVsID0gJ1N0ZXAgNC4gUFJPRklUJ10NCiAgDQogICMgZWRnZSBkZWZpbml0aW9ucyB3aXRoIHRoZSBub2RlIElEcw0KICByZWMxIC0+IHJlYzIgLT4gcmVjMyAtPiByZWM0DQogIH0iLA0KICBoZWlnaHQgPSA1MCkNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgYV9ncmFwaCA8LQ0KIyAgICBjcmVhdGVfZ3JhcGgoKSAlPiUgDQojICAgIGFkZF9ub2RlKCkgJT4lIA0KIyAgICBhZGRfbm9kZSgpICU+JSANCiMgICAgYWRkX2VkZ2UoDQojICAgICAgZnJvbSA9IDEsDQojICAgICAgdG8gPSAyDQojICAgICkgJT4lIA0KIyAgIGFkZF9ub2Rlc19mcm9tX3RhYmxlKA0KIyAgICAgdGFibGUgPSBub2RlX2xpc3RfMSwNCiMgICAgIGxhYmVsX2NvbCA9IGxhYmVsDQojICAgKSAlPiUgDQojICAgcmVuZGVyX2dyYXBoKGxheW91dCA9ICJuaWNlbHkiKQ0KIyANCiMgZ2V0X25vZGVfZGYoYV9ncmFwaCkNCmBgYA0KDQpgYGB7bWVybWFpZCwgZWNobz1GQUxTRX0NCiAgZ3JhcGggVEQ7DQogICAgICBBLS0+Qg0KYGBgDQoNCiMjIFINCg0KW1IgZm9yIERhdGEgU2NpZW5jZV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei9pbnRyb2R1Y3Rpb24uaHRtbCkNCg0KPiBVbSBkb3MgcHJpbmNpcGFpcyBsaXZyb3MgcGFyYSBxdWVtIGVzdMOhIHF1ZXJlbmRvIGFwcmVuZGVyIFIuIEVzc2Egw6kgYSAxwqogdmVyc8OjbywgcHVibGljYWRhIGVtIDIwMTcuIEVtIDIwMjMgc2Vyw6EgcHVibGljYWRhIGEgMsKqLCBhdHJhdsOpcyBkbyBbbGlua10oaHR0cHM6Ly9yNGRzLmhhZGxleS5ueikuDQoNCiMjIENoZWF0c2hlZXRzIHsjc2VjLWNoZWF0c2hlZXRzfQ0KDQpbQ2hlYXRzaGVldHNdKGh0dHBzOi8vcG9zaXQuY28vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLykNCg0KW0dpdEh1YiBjb20gYXMgdmVyc8O1ZXMgbWFpcyBhdHVhbGl6YWRhc10oaHR0cHM6Ly9naXRodWIuY29tL3JzdHVkaW8vY2hlYXRzaGVldHMvKQ0KDQpbZ2dwbG90MiBjaGVhdHNoZWV0XShodHRwczovL3Bvc2l0LmNvL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDIyLzEwL2RhdGEtdmlzdWFsaXphdGlvbi0xLnBkZikNCg0KW2dncGxvdDIgY2hlYXRzaGVldCBlbSBwb3J0dWd1w6pzXShodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcnN0dWRpby9jaGVhdHNoZWV0cy9tYWluL3RyYW5zbGF0aW9ucy9wb3J0dWd1ZXNlL2RhdGEtdmlzdWFsaXphdGlvbl9wdC5wZGYpDQoNClttYW5pcHVsYcOnw6NvIGRlIGRhZG9zIGVtIHBvcnR1Z3XDqnNdKGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9yc3R1ZGlvL2NoZWF0c2hlZXRzL21haW4vdHJhbnNsYXRpb25zL3BvcnR1Z3Vlc2UvZGF0YS13cmFuZ2xpbmdfcHQucGRmKQ0KDQpbZHBseXIgY2hlYXRzaGVldF0oaHR0cHM6Ly9wb3NpdC5jby93cC1jb250ZW50L3VwbG9hZHMvMjAyMi8xMC9kYXRhLXRyYW5zZm9ybWF0aW9uLTEucGRmKQ0KDQojIyBSbWFya2Rvd24geyNzZWMtcm1hcmtkb3dufQ0KDQpbVHV0b3JpYWwgc29icmUgUk1hcmtkb3duXShodHRwczovL3lvdXR1LmJlLzE4QVVaT1dBYXpnKQ0KDQpbUm1hcmtkb3duIGJhc2ljc10oaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20vYXV0aG9yaW5nX2Jhc2ljcy5odG1sKQ0KDQpbUk1hcmtkb3duOiBUaGUgZGVmaW5pdGl2ZSBndWlkZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLykNCg0KIyMgUGFjb3Rlcw0KDQpba25pdHJdKGh0dHBzOi8veWlodWkub3JnL2tuaXRyL29wdGlvbnMvKXsucGFjb3Rlc30NCg0KW2ludHJvMnJdKGh0dHBzOi8vaW50cm8yci5jb20vZ3JhcGhpY3Nfci5odG1sKQ0KDQotICAgR2V0dGluZyBzdGFydGVkIHdpdGggUiBhbmQgUlN0dWRpbw0KDQotICAgU29tZSBSIGJhc2ljcw0KDQotICAgRGF0YSBpbiBSDQoNCi0gICBHcmFwaGljcyB3aXRoIGdncGxvdA0KDQotICAgU2ltcGxlIFN0YXRpc3RpY3MgaW4gUg0KDQotICAgUmVwcm9kdWNpYmxlIHJlcG9ydHMgd2l0aCBSIG1hcmtkb3duDQoNCiMjIENhbmFpcyBubyBZb3V0dWJlIHsjc2VjLWNhbmFpcy1uby15b3V0dWJlfQ0KDQpbUGF0IFNjaGxvc3NdKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL0BSaWZmb21vbmFzKSAjZXNzZSBjYXJhIMOpIGdlbmlhbA0KDQpbQW1iaWVudGFsIFBybyBEZXZdKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL0BhbWJpZW50YWxwcm9kZXY1Mzc5KQ0KDQpbTWFyY2VsbyBDYXJ2YWxobyBSaWJlaXJvIC0gWW91dHViZV0oaHR0cHM6Ly93d3cueW91dHViZS5jb20vQGNhcnZhbGhvcmliZWlybykNCg0KLSAgIFRlbSBvIFtCbG9nXShodHRwczovL2NhcnZhbGhvcmliZWlyby5uZXRsaWZ5LmFwcC8pIGRlbGUgdGFtYsOpbS4NCg0KW0Zlcm5hbmRhIFBlcmVzXShodHRwczovL3d3dy55b3V0dWJlLmNvbS9ARmVybmFuZGFQZXJlcykNCg0KW01hcmluIFN0YXRzXShodHRwczovL3d3dy55b3V0dWJlLmNvbS9AbWFyaW5zdGF0bGVjdHVyZXMpDQoNCiMgQWluZGEgcHJlY2lzYSBzZXIgaW1wbGVtZW50YWRvL2FqdXN0YWRvIHsjc2VjLWFpbmRhLXByZWNpc2Etc2VyLWltcGxlbWVudGFkb2FqdXN0YWRvIC51bm51bWJlcmVkfQ0KDQotICAgUlPDgWd1YSBkZXZlIGJ1c2NhciBkYWRvcyBhbnRlcmlvcmVzIGEgMjAxNS4NCi0gICBBIEZlcGFtIHRlbSBvcyBkYWRvcyBkZSBgYWx0aXR1ZGVgIGRhcyBlc3Rhw6fDtWVzLiBBIHBhcnRpciBkaXNzbyBwb2RlIHNlciBjYWxjdWxhZG8gbyBgJSBkZSBzYXR1cmHDp8OjbyBkZSBPeGlnw6puaW8gRGlzc29sdmlkb2AsIG5lY2Vzc8OhcmlvIHBhcmEgbyBjw6FsY3VsbyBkbyBJUUEuDQotICAgVG9ybmFyIGEgY29sdW5hIGRlIGBjaHV2YV8yNGhgIGNvbW8gZmFjdG9yLg0KLSAgIEEgY29sdW5hIGBob3JhX2NvbGV0YWAgZXN0w6EgY29tIGZvcm1hdG8gaW5jb3JyZXRvLg0KLSAgIEdlcmFyIHVtIGBTaGlueSBXZWIgQXBwYA0KLSAgIH5+VG9ybmFyIGEgY29sdW5hIGRlIGBtdW5pY2lwaW9gIGNvbSBhcGVuYXMgYSBwcmltZWlyYSBsZXRyYSBtYWnDunNjdWxhLn5+DQotICAgU2luY3Jvbml6YcOnw6NvIHZpYSBHaXRIdWINCi0gICBBcHJlbmRlciBhIGdlcmFyIG8gbWFwYSBkZSBwcmVjaXBpdGHDp8OjbyBtZW5zYWwgcHJhIHRvZG8gbyBSUw0KICAgIC0gICBPIFJTIGVzdMOhIGVudHJlIDIgZnVzb3MsIGVudMOjbyBhY2FiYSAicGFydGluZG8gbm8gbWVpbyIgYSBmaWd1cmENCi0gICBGdXR1cmFtZW50ZTogaW50ZWdyYcOnw6NvIHZpYSBHb29nbGUgU2hlZXRzLg0KDQojIEluZm9ybWHDp8O1ZXMgYWRpY2lvbmFpcyB7I3NlYy1pbmZvcm1hw6fDtWVzLWFkaWNpb25haXMgLnVubnVtYmVyZWR9DQoNCkUtbWFpbCBwYXJhIGNvbnRhdG86IFtsZW9uYXJkb2Z3aW5rXEBnbWFpbC5jb21dKGxlb25hcmRvZndpbmtAZ21haWwuY29tKQ0KDQpHaXRIdWI6IDxodHRwczovL2dpdGh1Yi5jb20vbGVvbmFyZG9md2luay8+DQoNCkxpbmtlZEluOiA8aHR0cHM6Ly93d3cubGlua2VkaW4uY29tL2luL2xlb25hcmRvZndpbmsvPg0KDQpgYGB7ciBpbmNsdWRlID0gRkFMU0V9DQojIG5vIFlBTUwgZG8gY29kZSBjaHVuazoNCiMgcHJhIGVzY29uZGVyIG8gY8OzZGlnbw0KDQojIGNsYXNzLnNvdXJjZSA9ICdmb2xkLWhpZGUnIA0KIyBmb2xkLm91dHB1dD1GQUxTRSwgDQojIGZvbGQucGxvdD1GQUxTRQ0KYGBgDQo=